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); } }