Java中的Class Loader

Java的ClassLoader

Java中的ClassLoader采用Delegation机制。即每一个ClassLoader都有自己的Parent Class Loader,当从一个Class Loader中加载一个Class时,会先到当前ClassLoader的Parent中寻找该Class是否已经被加载,如果是,则从其Parent Class Loader中得到Class的Instance,如果没有,使用当前ClassLoader来加载Class。请看如下程序:

public class Test {
public static void main(String[] args) throws Exception {
Test test = new Test();
ClassLoader cl = test.getClass().getClassLoader();
while (cl != null) {
System.out.println("class loader is: " + cl.toString());
cl = cl.getParent();
}
}
}

在Windows上使用JDK1.5输出如下:
class loader is: sun.misc.Launcher$AppClassLoader@82ba41
class loader is: sun.misc.Launcher$ExtClassLoader@923e30

对于每一个Java进程都有一个System Class Loader,也叫Application Class Loader,用于加载写在CLASSPATH中的Class,并作为其它用户Class Loader的缺省的Parent Class Loader。由以上输出可以看到,Test类由System Class Loader加载,System Class Loader的Parent是Ext. Class Loader。Ext. Class Loader还具有一个Parent Class Loader,就是BootstrapClassLoader。该Class Loader是Java VM内置的Class Loader,用于加载java.*。如果使用ClassLoader.getParent()方法,当一个Class Loader的Parent是Bootstrap是,一般返回null。(Windows, Linux, Solaris均如此)

 

观察如下程序:

 

public class B {
public void method1() {
A a = new A();
...

}
}


public class B {
public void method1() {
Class clazz = Class.forName("A");
Object o = clazz.newInstance();
...
}
}

这两段程序都会从“Current Class Loader”来加载Class A。即从加载B Class的Class Loader来加载Class A。

 

Thread 的Context Class Loader

自从JDK1.2以后,Sun 为java.lang.thread加入了setContextClassLoader和getContextClassLoader两个方法,但是并没有指明应该如何使用。通常比较Confuse的是,当执行上述代码是,是从Thread的Context Class Loader中加载Class A,还是从加载Class B的Class Loader中加载A(如果两个ClassLoader不同的话)?答案是从加载B的Class Loader中加载A,而不是从Thread的Context Class Loader中加载A。那Context Class Loader是做什么用的呢?举例来说:在JDK1.4中,加入了XML的支持(JAXP),用户可以指定DocumentBuilder的Concrete Class,该Class需实现JAXP接口。在DocumentBuilderFactory中是使用Class.forName加载该Concrete Class的。DocumentBuilderFactory是使用Bootstrap Class Loader来加载的,但通常JAXP的实现都是位于CLASSPATH中,是由System Class Loader加载,而Bootstrap Class Loader又是System Class Loader的Ancestor Class Loader,即Bootstrap Class Loader不能从System Class Loader中加载Class。这时,就可以显式的使用Thread.getContextClassLoader来解决这一问题。而在JDK1.4中也正式这样实现的。

这里,我们再看一段程序:

public class Test {
public static void main(String[] args) throws Exception {
Test test = new Test();
ClassLoader cl = test.getClass().getClassLoader();
while (cl != null) {
System.out.println("class loader is: " + cl.toString());
cl = cl.getParent();
}

System.out.println("thread context class loader is: " + Thread.currentThread().getContextClassLoader());
System.out.println("system class loader is: " + ClassLoader.getSystemClassLoader());

Class clazz = Class.forName("java.lang.String");
System.out.println("bootstrap class loader is: " + clazz.getClassLoader());
}
}

在Windows上使用JDK1.5输出如下:
class loader is: sun.misc.Launcher$AppClassLoader@82ba41
class loader is: sun.misc.Launcher$ExtClassLoader@923e30
thread context class loader is: sun.misc.Launcher$AppClassLoader@82ba41
system class loader is: sun.misc.Launcher$AppClassLoader@82ba41
bootstrap class loader is: null

由此可见,在Java进程启动时,main thread的Context Class Loader即为System Class Loader。

 

参见:

http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值