JVM双亲委派模型及其优点

JVM双亲委派模型及其优点

什么是双亲委派模型?

双亲委派模型

​ 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式。

简单来说就是:

  • 首先从底向上检查类是否已经加载过
  • 如果都没有加载过的话,那么就自顶向下的尝试加载该类

为什么使用双亲委派模型?

1.避免字节码重复加载

采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。

2.程序更加安全,核心api不会被替换

​ 假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。相同的class文件被不同的classloader加载就是不同的两个类。

双亲委派模型类加载器分类:

1、启动类加载器(Bootstrap)C++写的
2、扩展类加载器(Extension)JAVA
3、应用程序类加载器(AppClassLoader)也叫做系统类加载器,加载当前应用的classpath下的所有类。
4、用户自定义加载器:
Java.lang.ClassLoader的子类,用户可以定制类的加载方式。

打印加载器的加载路径:

import sun.misc.Launcher;
import sun.misc.URLClassPath;
import java.net.URL;
import java.net.URLClassLoader;

public class Example {
    public static void main(String[] args) {
        //打印启动类加载器的加载路径
        URLClassPath bootstrapClassPath = Launcher.getBootstrapClassPath();
        for(URL url : bootstrapClassPath.getURLs()){
            System.out.println(url.getPath());
        }
        //打印扩展类加载器的加载路径
        URLClassLoader extClassLoader = 		(URLClassLoader)ClassLoader.getSystemClassLoader().getParent();
        for(URL url : extClassLoader.getURLs()) {
            System.out.println(url.getPath());
        }
        //打印应用程序类加载器加载路径
        URLClassLoader appClassLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
        for(URL url : appClassLoader.getURLs()) {
            System.out.println(url.getPath());
        }
    }
}

打印加载器实例对象:

BootStrapClassLoader 是一个纯的C++实现,没有对应的Java类。如果一个类的classloader是null。证明其是由BootStrapClassLoader 加载的。

public class Example {
    public static void main(String[] args) {
        System.out.println(Example.class.getClassLoader());
        System.out.println(Example.class.getClassLoader().getParent());
        System.out.println(Example.class.getClassLoader().getParent().getParent());
    }
    
/*  输出:
	sun.misc.Launcher$AppClassLoader@18b4aac2
    sun.misc.Launcher$ExtClassLoader@4554617c
	null*/

}
posted @ 2021-07-25 19:14  aixueforever  阅读(453)  评论(0编辑  收藏  举报