good:
- package test;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.lang.reflect.Method;
- public class CompileClassLoader extends ClassLoader{
- //读取一个文件的内容(即Class文件,如Hello.class)
- private byte[] getBytes(String filename) throws IOException{
- File file = new File(filename);
- long len = file.length();
- byte[] raw = new byte[(int)len];
- FileInputStream fis = null;
- try{
- fis = new FileInputStream(file);
- //一次读取Class文件的全部二进制数据
- int r = fis.read(raw);
- if(r != len)
- throw new IOException("无法读取全部文件:"+r+"!="+len);
- return raw;
- }catch(IOException ioe){
- throw new RuntimeException("读取文件失败!");
- }finally{
- try{
- if(fis != null)
- fis.close();
- }catch(IOException ioe){
- throw new RuntimeException("读取流关闭失败!");
- }
- }
- }
-
- //定义编译指定Java源文件的方法
- private boolean compile(String javaFilename) throws IOException{
- System.out.println("CompileClassLoader:正在编译"+javaFilename+"...");
- //调用系统的Javac命令
- Process p = Runtime.getRuntime().exec("javac "+javaFilename);
- try{
- //其它线程都等待这个线程完成
- p.waitFor();
- }catch(InterruptedException ie){
- ie.printStackTrace();
- }
- //获取javac线程的退出值
- int ret = p.exitValue();
- //返回编译是否成功
- return ret == 0;
- }
-
- //重写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源文件存在,且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 ioe){
- ioe.printStackTrace();
- }
- }
- //如果Class文件存在,系统负责将该文件转化成Class对象
- if(classFile.exists()){
- try{
- //将class文件的二进制数据读入数组
- byte[] raw = getBytes(classFilename);
- //调用ClassLoader的defineClass方法将二进制数据转换成Class对象
- clazz = defineClass(name, raw, 0, raw.length);
- }catch(IOException ioe){
- ioe.printStackTrace();
- }
- }
- //如果clazz为null,表名加载失败,则抛出异常
- if(clazz == null){
- throw new ClassNotFoundException(name);
- }
- return clazz;
- }
-
- //定义主方法
- public static void main(String[] args) throws Exception{
- //如果运行该程序(自定义类加载器CompileClassLoader)时没有参数,即没有目标类
- if(args.length<1){
- System.out.println("缺少目标类,请按如下格式运行Java源文件:");
- System.out.println("java CompileClassLoader ClassName");
- return;
- }
- //第一个参数是需要运行的类
- String progClass = args[0];
- //剩下的参数将作为运行目标类是的参数
- //将这些参数复制到一个新数组中
- String[] progArgs = new String[args.length-1];
- System.arraycopy(args, 1, progArgs, 0, progArgs.length);
- CompileClassLoader ccl = new CompileClassLoader();
- //加载需要运行的类
- Class<?> clazz = ccl.loadClass(progClass);
- //获取需要运行的类的主方法
- Method main = clazz.getMethod("main", (new String[0]).getClass());
- Object[] argsArray = {progArgs};
- main.invoke(null, argsArray);
- }
- }
复制代码 |