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(FilelnputStream fin = new FilelnputStream(file)){
//一 次读取 Class 文件的全部 二 进制数据
int r = fin.read(raw);
if(r != len)
throw new IOException( " 无法读取全部文件: " + r + " != " + len);
return raw
}
}
//定义编译指定 Java文件的方法
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 ie){
System.out.println(ie);
}
//获取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("ClassNotFoundExcetpion:" + javaFilename);
}
catch (IOException ex)
{
ex.printStackTrace();
}
// 如果存在class文件,将其加载成为class对象
if(classFile.exists()){
try{
// 将class文件读取进数组
byte[ ] raw = getBytes(classFilename);
//调用 ClassLoader的defineClass 方法将二进制数据转换成Class对象
clazz = defineClass(name , raw , O , raw.length);
}catch(IOException e){
e.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception
// 如果运行该程序时没有参数,即没有目标类
if (args . length < 1)
System.out.println (" 缺少目标类 , i 青按如下格式运行 Java 源文件: " );
System.out.println( " java CompileClassLoader ClassName " ) ;
//第一个参数是需要运行的类
String progClass = args[0] ;
//剩下的参数将作为运行目标类时的参数
// 将这些参数复制到 一个新数组中
String [] progArgs = new String[args . length-l];
System.arraycopy(args , 1 , progArgs , 0 , progArgs . length) ;
Compile ClassLoader ccl = new CompileClassLoader();
//加载需要运行的类
Class<?> clazz = ccl . loadClass(progClass);
//获取需要运行的类的主方法
Method main = clazz . getMethod("main" , (new Strinq[0]) .getClass ()) ;
Object argsArray[] = {proqArqs} ;
main. invoke (null , arqsArray) ;
}
java类加载器
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- java类加载器主要分为如下几种: jvm提供的类加载器 根类加载器:底层实现,主要加载java核心类库(如:ja...
- 在《Java类加载器:类加载原理解析》提到的类加载器的双亲委派模型并不是一个强制性的约束模型,而是Java设计者...
- 摘要: 每个开发人员对java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这个异...
- 将class文件加载到虚拟机的内存中,这个过程称为类加载。 类加载的过程: 加载(Loading),类加载过程的一...