黑马程序员技术交流社区

标题: 系统加载器与自定义加载器的疑惑 [打印本页]

作者: 谢洋    时间: 2013-2-26 10:24
标题: 系统加载器与自定义加载器的疑惑
本帖最后由 谢洋 于 2013-2-26 20:42 编辑

package cn.itcast.classloader;
//自定义加载类的测试类
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.util.Date;
/**
* 类加载器,本身也是类:
* 系统默认三个类:
* BootStrap:专门加载JRE/lib/rt.jar中的类
* ExtClassLoader:专门加载JRE/lib/ext/*.jar中的类
* AppClassLoader:专门加载CLASSPATH指定的所有jar或目录中的类
* 类加载器的委托机制:
* 1,当子类加载器加载某个类时?
* @author Administrator
*
*/
public class ClassLoaderTest {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

  
  //打印加载当前线程的类加载器
  System.out.println("当前线程的类加载器:"+Thread.currentThread().getContextClassLoader().getClass().getName());

  /**
   * 加载指定的类:方式一,让爸爸(AppClassLoader)去找cn.itcast.classLoader.ClassLoaderAttachment,
   * 如没找到,子类(MyClassLoader)去
   * 此方式findClass()方法代码与方式二的findClass()你代码有些不同
   */
  //Class clazz = new MyClassLoader("itcastlib").loadClass("cn.itcast.classloader.ClassLoaderAttachment");
  
  /**
   * 加载指定的类:方式二,让爸爸去找类名是ClassLoaderAttachment,爸肯定找不找,这时只能是MyClassLoader找
   *  此方式findClass()方法代码与方式一的findClass()的代码有些不同
   */
  Class clazz = new MyClassLoader("itcastlib").loadClass("ClassLoaderAttachment");
  
  /**
   * ???????
   *张老师说这个类名不是很好的加载,但不明白为什么?
   *发现当字节码由AppClassLoader过载的就没有问,如果由MyClassLoade加载过的,(不管AppClassLoader的加载目录是否有这个类),
   *运行就会发生异常
   *1,(classpath路径下没有有这个类时发生的)Exception in thread "main" java.lang.NoClassDefFoundError: cn/itcast/classloader/ClassLoaderAttachment
   *2,(classpath路径下有这个类时发生的)java.lang.ClassCastException:cn.itcast.classloader.ClassLoaderAttachment cannot be cast to cn.itcast.classloader.ClassLoaderAttachment
   */
  System.out.println("谁加载ClassLoaderAttachment?:"+clazz.getClassLoader().getClass().getName());
  ClassLoaderAttachment d= (ClassLoaderAttachment) clazz.newInstance();
  Date d1 = (Date)clazz.newInstance();
  //打印加载该类加的载器。
  System.out.println(clazz.getClassLoader().getClass().getName());
  System.out.println(d1);
}
}
/*这里是MyClassLoader中findClass()的代码
@Override//当父类找不到才会执行这里
protected Class<?> findClass(String name) throws ClassNotFoundException {
//目录加上类的名称
//这种方式接收的name是cn.itcast.classLoader.ClassLoaderAttachment
//String classFileName=classDir +"\\"+ name.substring(name.lastIndexOf('.')+1) + ".class"; //itcast\ClassLoaderAttachment
//这种方式对应的name是ClassLoaderAttachment
String classFileName=classDir +"\\"+ name + ".class";
try{
  //把要加载的类关联到流上
  FileInputStream fis = new FileInputStream(classFileName);
  ByteArrayOutputStream bos = new ByteArrayOutputStream();
  //因为本例中itcastlib中的类是过加载必的,所以在此要解密
  cypher(fis,bos);
  fis.close();
  //
  byte[] bytes = bos.toByteArray();
  //得到一个Class 实例
  System.out.println("zi zhao");//测试是否是子加载的
  return defineClass(bytes,0,bytes.length);
  //return defineClass(name,bytes,0,bytes.length);
}catch(Exception e){
  e.printStackTrace();
}
System.out.println("myclassloader");
return null;
//return super.findClass(name);
}
//这个例子是张老师在基础加强中:类加载的案例源代码已放到附件中
疑问:
1,(classpath路径下没有这个类时发生的)Exception in thread "main" java.lang.NoClassDefFoundError: cn/itcast/classloader/ClassLoaderAttachment
发生条件是:ClassLoaderAttachment是由MyClassLoader加载,且classpath下没ClassLoaderAttachment.class时发生的,
为什么ClassLoaderAttachment已经加载入进了,还去cn/itcast/classloader/ClassLoaderAttachment这里找?
2,(classpath路径下有这个类时发生的)java.lang.ClassCastException:cn.itcast.classloader.ClassLoaderAttachment cannot be cast to cn.itcast.classloader.ClassLoaderAttachment
发生条件:ClassLoaderAttachment是由MyClassLoader加载,且classpath有ClassLoaderAttachment.class时发生的
难道ClassLoaderAttachment被加载两次:一次是由MyClassLoader加载,一次是由AppClasssLoader加载?
如果是,那么为什么不能强转?不是同一份子节码吗?
3,如果是由AppClasslLoader加载过或,直接执行这条语句时,ClassLoaderAttachment d= (ClassLoaderAttachment) clazz.newInstance();这是就不发生异常
*/

源代码cn.zip

4.11 KB, 下载次数: 83

程序代码


作者: 黑马刘杰    时间: 2013-2-26 11:26
我这一块也不清楚,求高手详解
作者: vaanmax    时间: 2013-2-26 12:03
同求 详解。。。




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