深入JVM内核---类加载器和父类委托机制
类加载器:加载类的工具,只要你用到了哪个类,就需要把他的class(二级制文件)加载进来,这个工作就是类加载器来做的.java虚拟机上可以安装多个类加载器,系统默认有三个类加载器,Bootstrap(内嵌在java虚拟机内内核中由c++编写),ExtClassLoader,AppClassLoader,每个类负责加载特定位置的类.也可以自定义类加载器,自定义的加载器必须继承classLoader.
类加载器之间的关系和管辖范围:
父子关系:
bootstrap(爷爷)->ExtClassLoader(爸爸)->AppClassLoader(儿子)
它们的管辖范围依次是:
bootstrap--->JRE/lib/rt.jar
ExtClassLoader--->JRE/lib/ext/*.jar
AppClassLoader--->CLASSPATH指定的所有jar或目录
bootstrap:它不是java类,不需要被其他类加载器加载,跑在java虚拟内核里,java虚拟机内核一旦启动,他就有,他可以用来加载别的类或者类加载器.
在目录C:\Program Files\Java\jre1.8.0_66\lib下面的rt.jar都是由类加载器bootstrap加载的,平常用的jar包就是在这个目录下,例如util包,date包,hash包等等.
ExtClassLoader:
在目录C:\Program Files\Java\jre1.8.0_66\lib\ext下面都是类加载器ExtClassLoader加载,这个目录叫扩展目录
package jvm;
/**
* 用来讲解类加载器的三种类型
* Created by CXC on 2017/5/30.
*/
public class ClassLoaderTest {
//使用快捷键psvm,然后按回车即可
public static void main(String[] args) {
//ClassLoaderTest.class字节符
//ClassLoaderTest.class.getClass()获取到的是个类
//ClassLoaderTest.class.getClass().getName()得到类的名字
System.out.println(ClassLoaderTest.class.getClass().getName());
//为空指针,不代表他没有类加载器
System.out.println(System.class.getClassLoader());
//system他是由bootstrap加载器去加载的,他是嵌套在虚拟机内核里的,内核一已启动
System.out.println(System.class.getClassLoader());
ClassLoader loader=ClassLoaderTest.class.getClassLoader();
while (loader!=null){
//得到AppClassLoader
System.out.println(loader.getClass().getName());
loader=loader.getParent();
}
//得到ExtClassLoader
System.out.println(loader);
//打印的顺序为孙子,爸爸,爷爷,分别为AppClassLoader,ExtClassLoader,null(即boostrap)
}
}
父类委托机制
父类委托机制除了顶层的启动类加载器外,其他的类加载器都有自己的父类加载器.父类委托机制工作过程是:如果一个类加载器收到了类加载的请求的话,它首先不会自己去尝试加载这个类,而是把这个请求委托给父类加载器去完成,每一个层次的类加载器都是这样,因此所有的请求最终都应该传送到顶层的启动类加载器中,只有当父加载器无法完成这个请求时,会把这个请求发送给子类加载器,子类加载器才会自己去加载.