深入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 FilesJavajre1.8.0_66lib下面的rt.jar都是由类加载器bootstrap加载的,平常用的jar包就是在这个目录下,例如util,date,hash包等等.


ExtClassLoader:

在目录C:Program FilesJavajre1.8.0_66libext下面都是类加载器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)
    }
}

父类委托机制

  父类委托机制除了顶层的启动类加载器外,其他的类加载器都有自己的父类加载器.父类委托机制工作过程是:如果一个类加载器收到了类加载的请求的话,它首先不会自己去尝试加载这个类,而是把这个请求委托给父类加载器去完成,每一个层次的类加载器都是这样,因此所有的请求最终都应该传送到顶层的启动类加载器中,只有当父加载器无法完成这个请求时,会把这个请求发送给子类加载器,子类加载器才会自己去加载.



原文地址:https://www.cnblogs.com/chenxiaochan/p/7253401.html