类加载机制的学习2_____双亲委派模型

     通过之前的学习我们了解到了常见的三种类加载器:BootstrapClassLoader,ExtClassLoader,APPClassLoader,以及用户也可通过继承ClassLoader抽象类重新写findClass()来自定义类加载器。那么在类的加载中,怎么保证类的全局唯一性???在JVM中我们使用双亲委派机制来约定类加载器的加载机制。

双亲委派模型:

     在双亲委派模型中,除了启动类加载器(BootstrapClassLoader)外,每个类加载器都有一个超类加载器,如:AppClassLoader的超类加载器是ExtClassLoader,用户自定义类加载器是AppClassLoader。在实际进行类加载时,当前类加载器不会直接进行类的加载,而是会把类的加载任务委派给自己的超类加载器,超类加载器再委派给自己的超类加载器,直至到达顶层启动类加载器(BootstrapClassLoader),如果超类加载器无法加载委派给它的类,就会把加载任务再退会给自己的下一级加载器(如上图所示)。

    双亲委派机制的优点:可以有效的保证一个类的全局唯一性,当程序中出现多个全限定名相同的类时(比如两个类都叫:com.user.Test),类加载器执行加载时,始终只会加载其中的一个类,不会两个类都执行加载。

    双亲委派模型的源码阅读:

protected Class<?> loadClass(String var1, boolean var2) throws ClassNotFoundException {
        synchronized(this.getClassLoadingLock(var1)) {
            //首先检查 目标类型之前是否已经被加载过了
            Class var4 = this.findLoadedClass(var1);
            if (var4 == null) {
                long var5 = System.nanoTime();

                try {
                    //如果存在超类就委派给超类进行加载
                    if (this.parent != null) {
                        var4 = this.parent.loadClass(var1, false);
                    } else {
                       //如果不存在超类 就直接委派给 启动类加载器进行加载
                        var4 = this.findBootstrapClassOrNull(var1);
                    }
                } catch (ClassNotFoundException var10) {
                   //当抛出  ClassNotFoundException异常时 说明启动类加载器加载失败
                    ;
                }

                if (var4 == null) {
                //如果超累加载器无法加载。就自行进行加载
                    long var7 = System.nanoTime();
                    var4 = this.findClass(var1);
                    PerfCounter.getParentDelegationTime().addTime(var7 - var5);
                    PerfCounter.getFindClassTime().addElapsedTimeFrom(var7);
                    PerfCounter.getFindClasses().increment();
                }
            }

            if (var2) {
                this.resolveClass(var4);
            }

            return var4;
        }
    }
posted @ 2019-08-26 14:12  德鲁大叔817  阅读(231)  评论(0编辑  收藏  举报