import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.lang.reflect.Method; public class CompileClassLoader extends ClassLoader { // 定义一个主方法,args为待编译的类及所带的参数 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); // 加载待编译类并调用待编译类的main方法 CompileClassLoader compileClassLoader = new CompileClassLoader(); Class<?> clazz = compileClassLoader.loadClass(progClass); Method main = clazz.getMethod("main", (new String[0]).getClass()); Object[] argsArray = {progArgs}; main.invoke(null, argsArray); } // 重写ClassLoader的findClass方法 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源文件存在,但二进制文件不存在,或者java文件已更新,则进行重新编译 System.out.println(0000); if ((javaFile.exists() && (!classFile.exists())) || (javaFile.lastModified() > classFile.lastModified())) { try { if (!compile(javaFileName) || !classFile.exists()) { throw new ClassNotFoundException("ClassNotFoundException:" + javaFileName); } } catch (IOException e) { e.printStackTrace(); } } // 如果Class文件存在,系统负责将该文件转换成Class对象 if (classFile.exists()) { // 将Class文件的二进制数据读入数组 try { byte[] raw = getBytes(classFileName); // 调用Class Loader的defineClass方法将二进制数据转换成Class对象 clazz = defineClass(name, raw, 0, raw.length); } catch (IOException e) { e.printStackTrace(); } } // 如果Clazz为 null,表明加载失败,则抛出异常 if(clazz == null){ throw new ClassNotFoundException(name); } return clazz; } // 读取Class 二进制文件内容 private byte[] getBytes(String fileName) throws IOException { File file = new File(fileName); long length = file.length(); byte[] raw = new byte[(int) length]; FileInputStream fileInputStream = new FileInputStream(file); int read = fileInputStream.read(raw); fileInputStream.close(); if (read != length) { throw new IOException("无法读取全部文件:" + read + "!=" + length); } return raw; } // 使用系统javac命令进行编译 private boolean compile(String javaFile) throws IOException { System.out.println("CompileClassLoader:正在编译" + javaFile + "..."); Process exec = Runtime.getRuntime().exec("javac " + javaFile); try { exec.waitFor(); } catch (InterruptedException e) { System.out.println(e); } int exitValue = exec.exitValue(); return exitValue == 0; } }
注意:该类需要先经过javac进行编译,然后使用(java CompileClassLoader 其它待编译类)命令编译其它类,执行命令时注意包路径。
该类需要先经过javac进行编译,然后使用(java
CompileClassLoader 其它待编译类)进行编译