java findclass_java自定义类加载器(findClass和loadClass这两个方法的差别)

packagehuang.de.wei;importjava.io.File;importjava.io.FileInputStream;importjava.io.IOException;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;public class CompileClassLoader extendsClassLoader {//读取一个文件的内容

private byte[] getBytes(String filename) throwsIOException{

File file=newFile(filename);long len=file.length();byte[] raw=new byte[(int)len];

FileInputStream fin=newFileInputStream(file);//一次读取class文件的全部二进制数据

int r =fin.read(raw);if(r!=len)throw new IOException("无法读取全部文件:"+r+" != "

+len);

fin.close();returnraw;

}//定义编译指定的java文件的方法

private boolean compile(String javaFile) throwsIOException{

System.out.println("CompileClassLoader正在编译"+javaFile+"...");//调用系统的javac命令

Process p=Runtime.getRuntime().exec("javac"+javaFile);//其他的线程都在等待这个线程完成

try{

p.waitFor();

}catch(InterruptedException e) {//TODO Auto-generated catch block

System.out.println(e);;

}//获取javac线程的退出值

int ret =p.exitValue();return ret ==0;

}//重写ClassLoader的findClass方法

protected Class>findClass(String name){

System.out.println("进入findClass内部");

Class clazz=null;//将包路径中的点(.)替换成斜线(/)。

String fileStub=name.replace(".", "/");

String javaFilename="src/"+fileStub+"java";

String ClassFilename="bin/"+fileStub+".class";

File javaFile=newFile(javaFilename);

File classFile=newFile(ClassFilename);//当指定的java源文件存在,且class文件不存在,或者java源文件的//修改时间比class文件修改时间晚时,重新编译

if(javaFile.exists()&&(!classFile.exists())||javaFile.lastModified()>classFile.lastModified())

{//如果编译失败,或者该class文件不存在

try{if(!compile(javaFilename)||!classFile.exists()){

}

}catch(IOException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}//如果class文件存在,系统负责将该文件转化成class对象

if(classFile.exists()){try{byte[] raw =getBytes(ClassFilename);//调用ClassLoader的defineClass方法将二进制数据转换成class对象

clazz=defineClass(name,raw,0,raw.length);

}catch(IOException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}//如果clazz为null,表明加载失败,则抛出异常

if(clazz==null){try{throw newClassNotFoundException(name);

}catch(ClassNotFoundException e) {//TODO Auto-generated catch block

System.out.println("找不到这个类");

System.out.println(e.toString());;

System.out.println("找不到这个类");

}

}returnclazz;

}//定义一个主方法

public static void main(String[] args) throwsException{/*//如果运行程序没有参数,即没有目标类

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 ccl=new CompileClassLoader();

//加载需要运行的类

Class> clazz =ccl.loadClass(progClass);

//加载需要运行的类的主方法

Method main=clazz.getMethod("main",(new String[0].getClass()));

Object argspArray[] ={progArgs};

main.invoke(null, argspArray);*/

//如果运行该程序时没有参数,即没有目标类

args = new String[]{"huang.de.wei.Hello","嘿嘿"};//第一个参数是需要运行的类

String progClass = args[0];

System.out.println(args[0]);//剩下的参数将作为运行目标类时的参数,//将这些参数复制到一个新数组中

String[] progArgs = new String[args.length-1];

System.out.println(progArgs);

System.arraycopy(args ,1, progArgs

,0, progArgs.length);

CompileClassLoader ccl= newCompileClassLoader();//加载需要运行的类

Class> clazz =ccl.findClass(progClass);//获取需要运行的类的主方法

Method main = clazz.getMethod("main" , (new String[0]).getClass());

Object[] argsArray={progArgs};

main.invoke(null,argsArray);

}

}

被加载的类:

packagehuang.de.wei;public classHello {public static voidmain(String[] args){

System.out.println("tes22t2");for(String arg : args)

{

System.out.println("运行Hello的参数:" +arg);

}

}

}

运行结果:

huang.de.wei.Hello

[Ljava.lang.String;@1fc4bec

进入findClass内部

tes22t2

运行Hello的参数:嘿嘿

如果把   Class> clazz = ccl.findClass(progClass);改成  Class> clazz = ccl.loadClass(progClass);则程序运行不会进入我们重写的findClass方法内部,这时候遇到什么情况程序会进入findClass内部呢?其实Class> clazz = ccl.loadClass(progClass);这句的运行机制是这样的,如果loadClass()方法找不到需要被加载的类(这个代码示例是用huang.de.wei.Hello这个类当做被加载的类),则再到findClass()方法里面找。

如果

Class> clazz = ccl.findClass(progClass);

改为

Class> clazz = ccl.loadClass(progClass);

且:

args = new String[]{"huang.de.wei.Hello","嘿嘿"};

改为:

args = new String[]{"huang.de.wei.Hello2","嘿嘿"};//Hello2这个类不存在,程序用loadClass()方法找不到,就再调用findClass再找

运行结果如下:

huang.de.wei.Hello2

[Ljava.lang.String;@1fc4bec

进入findClass内部

找不到这个类

java.lang.ClassNotFoundException: huang.de.wei.Hello2

找不到这个类

Exception in thread "main" java.lang.NullPointerException

at huang.de.wei.CompileClassLoader.main(CompileClassLoader.java:136)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值