黑马程序员技术交流社区

标题: 学习类加载器遇到了一个问题 [打印本页]

作者: hhmm665544    时间: 2014-4-9 23:12
标题: 学习类加载器遇到了一个问题
自己写的类加载器
  1. @Override
  2.         protected Class<?> findClass(String name) throws ClassNotFoundException{
  3.                 String destPath = Path+"\\"+name+".class";
  4.                 try{
  5.                         FileInputStream ips = new FileInputStream(destPath);
  6.                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
  7.                         MyClassLoader.cypher(ips, bos);
  8.                         byte[] buf = bos.toByteArray();
  9.                         return defineClass(buf,0,buf.length);
  10.                         //return super.findClass(name);
  11.                 }catch(Exception e){
  12.                         //throw new RuntimeException(e);
  13.                        
  14.                 }
  15.                 return super.findClass(name);
  16.         }
  17.         private String Path;
  18.         PersonLoader(){
  19.                
  20.         }
  21.         PersonLoader(String Path){
  22.                 this.Path = Path;
  23.         }
复制代码

如果把覆盖的findClass里面的String destPath = Path+"\\"+name+".class";改成String destPath = Path+"\\"+nam;Class clazz = new PersonLoader("D:\\workspace\\高新技术\\lib").loadClass("Person.class");会调用自己的类加载器去加载lib文件夹里面的那份字节码
但是String destPath = Path+"\\"+name+".class";
Class clazz = new PersonLoader("D:\\workspace\\高新技术\\lib").loadClass("Person");就会去调用sun.misc.Launcher$AppClassLoader去加载.还会报错
Exception in thread "main" java.lang.NoClassDefFoundError: Person (wrong name: cn/hmm/classLoadTest/Person)


感觉好神奇啊,求大神解答一下

作者: yanzhendong    时间: 2014-4-10 00:34
是这样的,你可能将D:\\workspace\\高新技术\\lib添加到了buildPath,因类加载器的委托机制,会首先调用父类的findClass()函数,父类的findClass()函数在buildPath中找到了Person类,但这个类不属于D:\\workspace\\高新技术\\lib这个路径,他属于cn/hmm/classLoadTest/Person这个包,所有你需要将Person类放回到他属于的包才能加载,可以将目录D:\\workspace\\高新技术\\lib从buildPath中移除,这样父类在buildPath路径中就找不到Person类了就会调用子类的findClass()函数,你传入“Person.class”之所以能成功是因为父类在寻找Class时是以Person.class.class名称来找的,这样父类就找不到Person类了,就会调用子类的findClass函数
作者: hhmm665544    时间: 2014-4-10 22:32
yanzhendong 发表于 2014-4-10 00:34
是这样的,你可能将D:\\workspace\\高新技术\\lib添加到了buildPath,因类加载器的委托机制,会首先调用父 ...

我把包里面的那个class给删除掉了,但是他还是不会去用我自己写的那个类加载器去加载lib文件夹里面的字节码啊
作者: yanzhendong    时间: 2014-4-11 08:20
你要把buildPath删除,就像这样

QQ截图20140411081618.png (4.81 KB, 下载次数: 12)

QQ截图20140411081618.png

QQ截图20140411081729.png (108.63 KB, 下载次数: 13)

QQ截图20140411081729.png

QQ截图20140411081923.png (107.71 KB, 下载次数: 18)

QQ截图20140411081923.png

作者: leon_hm    时间: 2014-4-11 09:08
如果是sun.misc.Launcher$AppClassLoader 去加载,生成的类名应该是cn/hmm/classLoadTest/Person.class而不应该是cn/hmm/classLoadTest/Person
作者: xiaochen33520    时间: 2014-4-11 10:29
直接把myEclipse编译的class字节码文件去掉,然后通过输入流指向加密后的字节码文件进行解密写入ByteArrayOutputStream,还有,就是张老师讲类加载器时,通过window-->show view 调出 problems视图,再看看,也许是jre还是读的原来的一个字节码文件,需要重启一下myeclipse;这里我不是很清楚了,好像是这样的

作者: yanzhendong    时间: 2014-4-11 11:06
刚大概理清了头绪,当父类加载器找到类时,会将这个类的名字和类里面定义的包名进行比较,不一样的话就会抛出NoClassDefFoundError,比如你传入的Person类在当前目录下找到了假如当前目录是cn/hmm,但是这个类里面的package定义的是package cn.hmm.classLoadTest;这样类找到的实际路劲和类里面定义的路径不一样,就会出现这样的异常




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2