Classloader精简重点

时间:2022-07-12 14:00:35

如果想学习classloader的具体内容,请goodu

JVM 在运行时会产生三个ClassLoader,Bootstrap ClassLoader、Extension ClassLoader和 App ClassLoader。

Bootstrap ClassLoader是用C++编写的,在Java中看不到它,是null。它用来加载核 心类库,就是在lib下的类库。

Extension ClassLoader加载lib/ext下的类库。

App ClassLoader加载 Classpath里的类库。

三者的关系为:App ClassLoader的Parent是Extension ClassLoader,而 Extension ClassLoader的Parent为Bootstrap ClassLoader。加载一个类时,首先BootStrap进行寻 找,找不到再由Extension ClassLoader寻找,最后才是App ClassLoader。  但,这个Parent关系只是他们之间类加载和查找的关系Extension ClassLoader的实现中,parent其实是null。Bootstrap会创建一个Launcher,这个Launcher 会根据系统和命令设定初始化好class loader结构,JVM就用它来获得extension classloader和system classloader,并载入所有的需要载入的Class,最后执行java命令指定的带有静态的main方法的Class。extension classloader实际上是sun.misc.LauncherExtClassLoader类的一个实例,systemclassloader实际上是sun.misc.LauncherExtClassLoader类的一个实例,systemclassloader实际上是sun.misc.LauncherAppClassLoader类的一个实例。并且都是 java.net.URLClassLoader的子类。

代码:

 package com.saitama.classloader;

 import java.net.URL;

 import org.junit.Test;

 public class ClassLoaderTest {

     @Test
public void getClassPath(){
System.out.println(sun.misc.Launcher.class.getClassLoader());
System.out.println(sun.misc.Launcher.getLauncher().getClass().getClassLoader());
System.out.println(sun.misc.Launcher.getLauncher().getClassLoader());
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (int i = 0; i < urls.length; i++) {
System.out.println(urls[i].toExternalForm());
} ClassLoader loader = ClassLoaderTest.class.getClassLoader();
while(loader != null) {
System.out.println(loader);
loader = loader.getParent();
}
System.out.println(loader);
}
}

另外,JVM启动的时候可以设置参数指定每一个classloader类加载的路径。

context classloader有什么用呢?我们在建立一个线程Thread的时候,可以为这个线程通过setContextClassLoader方法来指定一个合适的classloader作为这个线程的context classloader,当此线程运行的时候,我们可以通过getContextClassLoader方法来获得此context classloader,就可以用它来载入我们所需要的Class。默认的是system classloader。利用这个特性,我们可以“打破”classloader委托机制了,父classloader可以获得当前线程的context classloader,而这个context classloader可以是它的子classloader或者其他的 classloader,那么父classloader就可以从其获得所需的 Class,这就打破了只能向父classloader请求的限制了。这个机制可以满足当我们的classpath是在运行时才确定,并由定制的 classloader加载的时候,由system classloader(即在jvm classpath中)加载的class可以通过context classloader获得定制的classloader并加载入特定的class(通常是抽象类和接口,定制的classloader中是其实现),例如web应用中的servlet就是用这种机制加载的.