zoukankan      html  css  js  c++  java
  • 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*/
    
    }
    
  • 相关阅读:
    论文引用标记设置
    悬浮图层特效
    SocketInputStream.socketRead0引起线程池提交任务后,futureTask.get超时
    线程池中的线程何时死亡?
    AppClassLoader
    《Java高并发编程详解-多线程架构与设计》Java Classloader
    Tomcat的类加载器初步认识
    《Java高并发编程详解-多线程架构与设计》Thread API
    《Java高并发编程详解-多线程架构与设计》JVM类加载器
    SpringMVC中的RootWebApplicationContext与ServletWebApplicationContext
  • 原文地址:https://www.cnblogs.com/aslanvon/p/15058699.html
Copyright © 2011-2022 走看看