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 其它待编译类)进行编译