栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JVM~类加载器之双亲委派模型

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JVM~类加载器之双亲委派模型

加油,新时代打工人。

首先,我们简单了解什么是双亲委派模型?

JDK 9 之前的 Java应用都是由这三种类加载器互相配合来完成加载的,如果用户认为有必要,还可以加入自定义的类加载器来进行拓展,典型的如增加除了磁盘位置之外的
Class 文件来源,或者通过类加载器实现类的隔离、重载等功能。这些类加载器之间的协作关系“通常”会如下图
所示。图中展示的各种类加载器之间的层次关系被称为类加载器的“双亲委派模型(Parents Delegation Model)”。


我们直接来看源码

    public static void main( String[] args ) throws Exception {
        System.out.println("--------获取类信息----------");
        Student student=new Student();
        Class aClass = student.getClass();

        System.out.println(aClass);
        System.out.println(aClass.getClassLoader());//获取类加载器
        System.out.println(aClass.getName());
        System.out.println(aClass.getPackage());
        }

通过上面反射的一段代码,有个getClassLoader(),获取到了类加载器
我们通过这个来看实现的源码,点击进去,

看到这段代码,首先,判断是否有类,没有返回null,有的话,就开始一系列的检查,返回的是类加载器的类型。这个时候我们在点击 ClassLoader,
里面实现了很多方法,我们找到 loadClass() 就看到下面类加载器的双亲委派模型的实现了。

  protected Class loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            //首先,检查类是否已经加载
            Class c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                    //如果找不到类,则抛出 ClassNotFoundException 
                    //来自非空父类加载器
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    // 如果仍未找到,则调用 findClass 以找到该类。
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    //这是定义类加载器;记录统计
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

这就比较有意思了,双亲委派的先检查是否已经加载的类,后面就是一顿的网上查,为什么说往上查,我看到parent.loadClass()父类加载器,往上找,如果父没有,在找子findClass()方法尝试加载的一个过程。

下面文字引用书籍中的。

双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。
使用双亲委派模型来组织类加载器之间的关系,一个显而易见的好处就是 Java 中的
类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类 java.lang.Object, 它存放在 rt.jar
之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此 Object
类在程序的各种类加载器环境中都能够保证是同一个类。反之,如果没有使用双亲委派模型,都由各个类加载器自行去加载的话,如果用户自己也编写了一个名为
java.lang.Object 的类,并放在程序的 ClassPath 中,那系统中就会出现多个不同的 Object 类,Java
类型体系中最基础的行为也就无从保证,应用程序将会变得一片混乱。如果读者有兴趣的话,可以尝试去写一个与 rt.jar 类库中已有类重名的
Java 类,将会发现它可以正常编译,但永远无法被加载运行

就到这里吧,尽量我多看源码用自己的话在总结其中的内涵吧,没有说到JVM的加载过程,多多看看和思考吧。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/711334.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号