自定义java类加载器

 
 

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

猜你喜欢

转载自blog.csdn.net/leadseczgw01/article/details/54862298