很早时就关注了classloader,但一直没有总结
1.classloader是树形结构。
bootstrap Class Loaders负责装载java.*下的基本类
extension Class Loaders负责装载javax.*下的类
system Class Loaders负责系统(用户)实现的类
三者的关系是
bootstrap class loaders是extension class loaders的父亲
extension class loaders是system class loaders的父亲
2.class loader的装载机制是parent delegate的模型。类的装载是委托给父class loader去查找,如果没有找到才用当前的class loader来查找。
3.不同的classLoader加载同一个类,实例是不同的,抛出castclassException
4.Class.forName是从指定的classloader中装载类,如果没有指定,也就是一个参数的时候,是从装载当前对象实例所在的classloader中装载类. 而ClassLoader的实例调用loadclass方法,是指从当前ClassLoader实例中调用类,而这个实例与装载当前所在类实例的Classloader也许不是同一个. 举个例子吧, 有A,B , C两个ClassLoader , 当前运行的类D的实例是d(装载它的是A) , 如果D中使用Class.forName那么就是使用的ClassLoader就是A,当然,也可以指定为B. 而如果D中代码找到的ClassLoader实例是C,那么就是用D来装载所指定的类.
5.Thread.currentThread().getContextClassLoader().loadClass("className"),采用当前线程的类加载器
比如:
1class A{
2..
3 public void test(){
4 ..
5 Class B =Thread.currentThread().getContextClassLoader().loadClass("className");
6 ..
7 }
8..
9}
如果将第5行中的的语句换成
1Class B=Class.forName("className")
这两种情况下calss B是一致的么?
回答:大多数情况下,是一样的,但是如果不改变 Thread的ClassLoader ,那么是否也是一样的呢?
考虑Java多线程应用,执行类A的方法体B中采用Tread的方式获得classloader是调用者的类加载器。而class.forname是加载当前类的也就是类A的类加载器。这两种情况下是可能不一致的。
在spring的环境下,类C中的类A实例通过依赖注入,如果采用Class.forName则Class B是IoC容器的类加载器;如果采用thread的话,则类加载器和加载类C的一样