zoukankan      html  css  js  c++  java
  • 双亲委派模型


    title: 双亲委派模型
    date: 2018-10-24 15:05:54
    tags:
    categories:

    双亲委派模型

    本来应该是jvm类加载机制的内容,但这个太重要了,我就单独写了一篇。jvm虚拟机有一个重要的判断(之一)两个类是否相等的依据,就是是否是同一个类加载器加载的类,首先要保证同一个类加载器加载,那么命名空间相等才有意义。

    加载器类型

    从java虚拟机的角度来说,有两种类加载器,一种是启动类加载器,另外就是其他类加载器。前者是由C++实现的,属于java虚拟机的一部分,后者使用Java语言实现的,并且继承自java.lang.ClassLoader。
    从java开发者来说则可以细分成三类:

    1. 启动类加载器(Bootstrap ClassLoader),这个就是上面说的启动类加载器,他负责加载<JAVA_HOME>lib目录中的类,还有-Xbootclasspath所指定路径中的,并且是虚拟机识别的类库。
    2. 扩展类加载器(Extension ClassLoader),这个加载器负责加载<JAVA_HOME>libext目录中的类,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用这个类加载器。
    3. 应用程序类加载器(Application ClassLoader),这个类加载器负责加载用户类路径(ClassPath)上所制定的类库,开发者也可以直接使用这个类加载器。

    双亲委派模型

    双亲委派模型就是按照顺序,以此使用这三种类加载器加载类,加载顺序如图所示。

    双亲委派模型
    ClassLoader中双亲委派模型源码实现:

    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
    }
    
    if (c == null) {
    // If still not found, then invoke findClass in order
    // to find the class.
    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;
    }
    }  
    

    我们在这里简单分析一下远吗,首先我们要判断这个类是否加载过,如果没有加载,则对这个类进行加载。
    加载是先调用父类加载器去加载(不断调用,不知道这里算不算递归??),如果父类加载器不存在,则被认为是Bootstrap加载器,这时候就直接使用这个类加载器进行加载,如果加载失败,就抛出异常。
    介绍完了双亲委派模型,我们要知道为什么要使用这种方式去加载类。

    1. 防止各个类使用不同的类加载器去加载,这样就会导致同一个如果在不同的地方被不同的类加载器加载后,结果会不一样。如果使用双亲委派模型,就能保证不论何时何地加载这个类,都是同样的结果。
    2. 保证类只加载一次,实际上与上面这条也有关联,因为从源码可以看到,在加载类之前要判断是否被加载过,因为加载机制是双亲委派模型,所以保证如果被加载一次,那么必然不会再被加载。
      我想到的原因就这些,如果还有原因欢迎补充。
  • 相关阅读:
    hdu 4614 线段树 二分
    cf 1066d 思维 二分
    lca 最大生成树 逆向思维 2018 徐州赛区网络预赛j
    rmq学习
    hdu 5692 dfs序 线段树
    dfs序介绍
    poj 3321 dfs序 树状数组 前向星
    cf 1060d 思维贪心
    【PAT甲级】1126 Eulerian Path (25分)
    【PAT甲级】1125 Chain the Ropes (25分)
  • 原文地址:https://www.cnblogs.com/zhoujiayong/p/10144606.html
Copyright © 2011-2022 走看看