类加载器
引导类加载器BootStrapClassLoader
- 这个类加载器由C/C++语言实现,嵌套在JVM内部
- 用来加载Java的核心类库(JAVA_HOME/jre/lib/rt.jar、resources.jar或sun.boot.class.path路径下内容),用于提供JVM自身需要的类
- 不继承java.lang.ClassLoader,没有父加载器 加载扩展类和应用程序类加载器,并指定为它们的父类加载器
- 出于安全考虑,BootStrap引导类加载器只加载包名为java、javax、sun等开头的类
扩展类加载器ExtClassLoader
- Java语言编写,由sun.misc.Launcher$ExtClassLoader实现
- 派生于ClassLoader类
- 父类加载器为引导类加载器BootstrapClassLoader
- 从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录下加载类库,如果用户创建的JAR文件放入到此目录,也会自动由扩展类加载器加载
系统类加载器AppClassLoader
- java语言编写,由sun.misc.Launcher$AppClassLoader实现
- 派生于ClassLoader类
- 父类加载器为扩展类加载器ExtClassLoader
- 它负责加载环境变量classpath或系统属性java.class.path指定路径下的类库
- 该类为程序默认的类加载器,java应用的类由它来完成加载
- 通过ClassLoader#getSystemClassLoader()方法可以获得此类加载器
public class ClassLoaderTest {
public static void main(String[] args) {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
ClassLoader extClassLoader = systemClassLoader.getParent();
System.out.println(extClassLoader);
ClassLoader bootstrapClassLoader = extClassLoader.getParent();
System.out.println(bootstrapClassLoader);
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
System.out.println(classLoader);
ClassLoader stringClassLoader = String.class.getClassLoader();
System.out.println(stringClassLoader);
}
}
import com.sun.net.ssl.internal.ssl.Provider;
import sun.security.ec.CurveDB;
import java.net.URL;
public class ClassLoader1 {
public static void main(String[] args) {
System.out.println("--------BootStrapClassLoader---------");
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (URL url : urls) {
System.out.println(url.toExternalForm());
}
ClassLoader classLoader = Provider.class.getClassLoader();
System.out.println(classLoader);
System.out.println("-----------ExtClassLoader------------");
String extDirs = System.getProperty("java.ext.dirs");
for (String path : extDirs.split(";")) {
System.out.println(path);
}
ClassLoader classLoader1 = CurveDB.class.getClassLoader();
System.out.println(classLoader1);
}
}
--------BootStrapClassLoader---------
file:/D:/Program%20Files/Java/jdk1.8.0_131/jre/lib/resources.jar
file:/D:/Program%20Files/Java/jdk1.8.0_131/jre/lib/rt.jar
file:/D:/Program%20Files/Java/jdk1.8.0_131/jre/lib/sunrsasign.jar
file:/D:/Program%20Files/Java/jdk1.8.0_131/jre/lib/jsse.jar
file:/D:/Program%20Files/Java/jdk1.8.0_131/jre/lib/jce.jar
file:/D:/Program%20Files/Java/jdk1.8.0_131/jre/lib/charsets.jar
file:/D:/Program%20Files/Java/jdk1.8.0_131/jre/lib/jfr.jar
file:/D:/Program%20Files/Java/jdk1.8.0_131/jre/classes
null
-----------ExtClassLoader------------
D:\Program Files\Java\jdk1.8.0_131\jre\lib\ext
C:\Windows\Sun\Java\lib\ext
sun.misc.Launcher$ExtClassLoader@29453f44
public class ClassLoader2 {
public static void main(String[] args) {
try {
ClassLoader classLoader = Class.forName("java.lang.String").getClassLoader();
System.out.println(classLoader);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
System.out.println(contextClassLoader);
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
}
}
双亲委派机制
- 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行
- 如果父类加载器还存在父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器
- 如果顶层的启动类加载器可以完成加载,就成功返回,倘若父类加载器无法完成加载任务,子加载器才会尝试自己去加载