双亲委派模型

类加载器介绍:
从虚拟机的角度说,只存在两种类加载器:
  • 一种是启动类加载器,这个类加载器使用C++编写,是虚拟机自身的一部分;
  • 另一种是所有其他类的加载器,这些类加载器使用Java编写,独立于虚拟机,并且全部继承自抽象类java.lang.ClassLoader;
 
从Java开发人员的角度看,类加载器可以细分为三种系统提供的类加载器:
  • 启动类加载器Bootstrap ClassLoader:这类加载器负责加Java_homelib目录中的或者-XBootclasspath路径指定的,并且是虚拟机识别的类库加载到虚拟机内存中。
  • 扩展类加载器Extension ClassLoader:这个加载器负责加载Java_homelibext目录中的或者有java.ext.dirs系统变量指定的路径下的类库,开发者可以直接使用扩展类加载器。
  • 应用程序类加载器Application ClassLoader:一般称为系统类加载器,它负责加载用户类路径上所指定的类库,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下都是使用应用程序类加载器;
 
双亲委派模型
类加载器的双亲委托模型是JDK1.2被引入的。双亲委派模型不是一个强制性的约束模型,而是Java设计者推荐给开发者的一种类加载器实现方式。
                                                       
如果上图所示的类加载器这种层次关系,称为类加载器的双亲委派模型。
双亲委派模型要求除了顶层的“启动类加载器”外,其他的类加载器必须有自己的父类加载器。(这里所说的子类与父类,一般不是由继承方式实现的,而是通过组合关系来复用父加载器的代码)
 
双亲委派模型的工作原理:
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给负责加载器去完成,每一层类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只由当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。
双亲委派模型优点:Java类随着它的类加载器一起具备了一种带有优先级的层次关系,例如类java.lang.Object它存在在rt.jar之中,无论哪个类加载器要加载这个类,最终都会委派给处于模型顶层的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写一个java.lang.Object类并放在ClassPath中,那么系统中将会存在多个不同的Object类。
双亲委派模式的具体实现在java.lang.Classloader类下的loadClass()方法中:
protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 首先,检查这个类是否已经被加载过。
            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) {
                    // 如果父加载器或者启动类加载器无法加载的时候,再调用本身的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;
        }
收藏文章数量从多到少与“把书读薄”是一个道理
原文地址:https://www.cnblogs.com/use-D/p/9749186.html