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@82ba41class 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@82ba41class loader is: sun.misc.Launcher$ExtClassLoader@923e30thread context class loader is: sun.misc.Launcher$AppClassLoader@82ba41system class loader is: sun.misc.Launcher$AppClassLoader@82ba41bootstrap class loader is: null由此可见,在Java进程启动时,main thread的Context Class Loader即为System Class Loader。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/duqing72/archive/2005/09/24/488512.aspx

 

你可能感兴趣的:(java,thread,windows,ext,sun)