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);


}

}

最新文章

  1. Redis五种数据类型命令介绍(4)
  2. java中的数据结构 --- 集合
  3. POJ1185 炮兵阵地
  4. Orchard源码分析(7.2):Controller相关
  5. vijosP1437简单的口令
  6. 解决CAS单点登录出现PKIX path building failed的问题
  7. Codeforces Round #312 (Div. 2) B.Amr and The Large Array
  8. 使用xmanager 远程redhat6.3
  9. push类型消息中间件-消息发布者(二)
  10. shell脚本调用C语言之字符串切分之strtok函数
  11. 201521123059 《Java程序设计》第六周学习总结
  12. selenium+java破解极验滑动验证码的示例代码
  13. java入门day03
  14. dos6章
  15. css点滴3—5种方式实现圆环
  16. [Micropython]TPYBoard v102 DIY照相机
  17. NOIP2018凉凉记
  18. vue-cli3初尝试之路径别名配置
  19. Xampp单独升级某个软件
  20. linux 三剑客之awk

热门文章

  1. Java 异常处理的误区和经验总结--转载
  2. Android 交错 GridView
  3. ifconfig命令详解
  4. eclipse 库 library jar包 工程 总结
  5. 必须声明标量变量 &quot;@列名&quot;
  6. nyoj 76
  7. hdu 2211
  8. ASP.NET获取根目录的方法集合
  9. sql - 修改结构
  10. 使用DML语句【weber出品必属精品】