类加载器

类的加载在JVM的外部实现。对于任意的一个类,都必须由加载它的类加载器和这个类本身共同确立其在Java虚拟机中的唯一性。JVM提供中类加载器。

启动类加载器(Bootstrap ClassLoader

负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath 参数指定路径中的,且被 虚拟机认可(按文件名识别,如 rt.jar)的类。

主要加载jre里面的lib目录下的jar’包

扩展类加载器(Extension ClassLoader)

负责加载 JAVA_HOME\lib\ext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类 库。

主要加载jre/lib/ext目录下的jar

应用程序类加载器(Application ClassLoader)

负责加载用户路径(classpath)上的类库。 JVM 通过双亲委派模型进行类的加载,当然我们也可以通过继承 java.lang.ClassLoader 实现自定义的类加载器。

public class Test {

    public static void main(String[] args){
        Test test = new Test();
        Class<? extends Test> testClass = test.getClass();
        System.out.println("testClass = " + testClass);
        // AppClassLoader
        System.out.println("testClass.getClassLoader() = " + testClass.getClassLoader());
        // ExtClassLoader
        System.out.println("testClass.getClassLoader().getParent() = " + testClass.getClassLoader().getParent());
        // null:实际上是启动类(根)加载器,底层由c/c++实现,java获取不到此对象
        System.out.println("testClass.getClassLoader().getParent().getParent() = " + testClass.getClassLoader().getParent().getParent());
    }
}

双亲委派机制

当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父 类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中, 只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的 Class),子类加载器才会尝试自己去加载。

采用双亲委派的一个好处是比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载 器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载 器最终得到的都是同样一个 Object 对象。

最后修改日期:2020-07-12

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。