本帖最后由 谢洋 于 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();这是就不发生异常
*/
|
|