java 自制类加载器的简单实现

jopen 11年前

import java.io.File;  import java.io.FileInputStream;  import java.io.IOException;  import java.lang.reflect.Method;      public class CompileClassLoader extends ClassLoader{      //读取一个文件的内容  private byte[] getBytes(String filename)throws IOException{  File file = new File(filename);  long len = file.length();  byte[] raw = new byte[(int)len];  try(  FileInputStream fin = new FileInputStream(file);  ){  //一次读取Class文件的全部二进制数据  int r = fin.read(raw);  if(r != len){  throw new IOException("无法读取全部文件:"+r+" != "+len);  }      return raw;  }  }    private boolean compile(String javaFile) throws IOException{  System.out.println("CompileClassLoader:正在编译 "+javaFile+"...");  //调用系统的javac命令  Process p = Runtime.getRuntime().exec("javac "+javaFile);  try{  p.waitFor();  }catch (InterruptedException e) {  System.out.println(e);  }  //获取javac线程的退出值  int ret = p.exitValue();  return ret == 0;  }    protected Class<?> findClass(String name) throws ClassNotFoundException{  Class clazz = null;  //将包路径中的点(.)替换成斜线(/)  String fileStub = name.replace(".", "/");  String javaFilename = fileStub + ".java";  String classFilename = fileStub + ".class";  File javaFile = new File(javaFilename);  File classFile = new File(classFilename);  //当指定的java源文件存在,且class文件不存在,或者Java源文件的修改时间比class文件的修改时间更晚时,重新编译  if(javaFile.exists()&&(!classFile.exists()||javaFile.lastModified()>classFile.lastModified())){  try{  //如果编译失败,或者改class文件不存在  if(!compile(javaFilename)||!classFile.exists()){  throw new ClassNotFoundException("ClassNotFoundException:"+javaFilename);  }  }catch (IOException e) {  e.printStackTrace();  }  }  //如果class文件存在,系统负责将该文件转换成class对象  if(classFile.exists()){  try{  //将class文件的二进制数据读入数组  byte[] raw = getBytes(classFilename);  //调用classloader的defineclass方法将二进制数据转换成class对象  clazz = defineClass(name, raw, 0, raw.length);  }catch(IOException e){  e.printStackTrace();  }  }  if(clazz==null){  throw new ClassNotFoundException(name);  }  return clazz;  }    public static void main(String[] args) throws Exception {  //如果运行该程序时没有参数,既没有目标类  if(args.length<1){  System.out.println("缺少目标类,请按如下格式运行java源文件:");  System.out.println("java CompileClassLoader ClassName");  }  //第一个参数是需要运行的类  String progClass = args[0];  //剩下的参数将作为运行目标类的参数  //将这些参数复制到一个新数组中  String[] progArgs = new String[args.length-1];  System.arraycopy(args, 1, progArgs, 0, progArgs.length);  CompileClassLoader cc1 = new CompileClassLoader();  //加载需要运行的类  Class<?> clazz = cc1.loadClass(progClass);  //获取需要运行的类的主要方法  Method main = clazz.getMethod("main",(new String[0]).getClass());  Object argsArray[] = {progArgs};  main.invoke(null, argsArray);  }      }