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

来源:互联网 发布:java获取天气预报 编辑:程序博客网 时间:2024/06/11 09:58
package com.xiaomo.reflex;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);}}
原创粉丝点击