ClassLoader的双亲委派模型

类加载器用以实现类加载功能,而且肯定被加载的类在Java虚拟机中的惟一性。java

注意:由同一个类加载器加载,则这两个类相等,由不一样的类加载器加载,则这两个类不相等。bash

咱们知道类加载器主要分为:ide

  • 启动类加载器
  • 扩展类加载器
  • 应用程序类加载器

启动类加载器

负责加载如下类:ui

  • 存放在JAVA_HOME\lib目录中的类;
  • 被-Xbootclasspath参数所指定路径中、而且是被虚拟机识别的类库。

注意:启动类加载器不能直接被java程序直接饮用。spa

扩展类加载器

负责加载如下类:code

  • JAVA_HOME\lib\ext目录中的类;
  • 被java.ext.dirs系统变量所指定的路径中的全部类。

注意:开发者能够直接使用扩展类加载器。cdn

应用程序类加载器

负责加载用户类路径(classpath)上所指定的类库。blog

注意:该类加载器也被称为系统类加载器,开发者能够直接使用该类加载器。若开发者没有自定义类加载器,程序默认使用该类加载器。开发

各类类加载器并非孤立的,而是互相配合使用。虚拟机

在java虚拟机中,各类类加载器配合使用的模型就是双亲委派模型

双亲委派模型

双亲委派模型的工做流程所有在ClassLoader的loadClass()方法中执行:

@Override 
protected Class<?> loadClass(String name, boolean resolve) 
        throws ClassNotFoundException { 
    Class<?> c = findLoadedClass(name); 

  // 检查须要加载的类是否已经被加载过
    if (c == null) { 
        try { 
             // 若没有加载,则调用父加载器的loadClass()方法
            if (parent != null) { 
                c = parent.loadClass(name, false); 
            }else{ 
                // 若父类加载器为空,则默认使用启动类加载器做为父加载器
                c=findBootstrapClassOrNull(name); 
            } 
        } catch (ClassNotFoundException e) { 
            // 若父类加载器加载失败会抛出ClassNotFoundException, 
            //说明父类加载器没法完成加载请求 
        } 
        if(c==null){ 
            // 在父类加载器没法加载时 
            // 再调用自己的findClass方法进行类加载 
            c=findClass(name); 
        } 
    } 
    if(resolve){ 
        resolveClass(c); 
    } 
    return c; 
}
复制代码

若一个类加载器收到了类加载请求:

步骤:

  • 把该类加载请求委派给父加载器父完成,而不是本身去加载;(每层的类加载器都是如此,所以全部的类加载请求最终都会交由启动类加载器去加载)
  • 只用当父类加载器反馈本身没法完成该加载请求时,自加载器才会本身加载。

优势:

Java类随着它的类加载器一块儿具有了一种带优先级的层次关系。

相关文章
相关标签/搜索