双亲委派模型(Parents Delegation Model)(JDK 8)
类加载器的
双亲委派模型在 JDK 1.2 时期被引入,并被广泛应用于此后几乎所有的 Java 程序中,但它并不是一个具有强制性的约束力的模型,而是 Java 设计者们推荐给开发者的一种加载器实现的最佳实践。
一、类加载器
Java 虚拟机设计团队有意把类加载阶段中的 “ 通过一个类的全限定名来获取描述该类的二进制字节流 ” 这个动作放到 Java 虚拟机外部去实现,以便让应用程序自己决定如何去获取所需的类。实现这个动作的代码被称为 “ 类加载器 ”(Class Loader)。
判断两个类的是否 “ 相等 ”,是由类和加载类的类加载器共同决定的。
这里包括 Class 对象的 equal(),isAssignableFrom(),isInstance()和 instanceof 关键字的判断。
二、双亲委派模型
2.1、双亲委派模型的建立
从虚拟机的角度,只有两种类加载器,一种启动类加载器(Bootstrap ClassLoader),使用 C++实现,是虚拟机的一部分,另一种是继承自抽象类java.lang.ClassLoader的启动器。
但是在虚拟机实际中,提供了三种类加载器:
- 启动类加载器(Bootstrap Class Loader):主要负责加载存放在
<JAVA_HOME>\lib目录下,或者被-Xbootclasspath参数指定的路径中存放的,Java虚拟机能识别的类名(如rt.jar、tools.jar等),的类。(加载请求委派给引导类加载器时,使用null的。) - 扩展类加载器(Extension Class Loader):主要负责加载
<JAVA_HOME>\lib\ext目录下,或者被java.ext.dirs系统变量所指定的路径中的所有类。sun.misc.Launcher.ExtClassLoader - 应用程序类加载器(Application Class Loader):复杂加载用户类路径(Classpath)上所有的类库,开发者可以直接在代码中使用这个类加载器(
java.lang.ClassLoader#getSystemClassLoader)。一般情况下系统默认的类加载器,也称 “ 系统类加载器 ”。sun.misc.Launcher.AppClassLoader
在虚拟机内部,加载器之间存在一定的关系如下:
而这种层级关系,是JDK 1.2以来,虚拟机设计者为开发者提供的类加载器最佳实践模型。这种类似父子关系的层级模型称为 “双亲委派模型(Parents Delegation Model)”。这种父子关系并不是依赖于继承,而是使用的组合。
双亲委派模型的工作过程如下:
- 当前类加载器首先从自己已经加载的类(缓存)中,查询是否此类已经加载,如果已经加载,则直接返回原来已经加载的类。
- 如果在当前类加载器的缓存中,没有找到期待被加载的类时,则委托父类加载器去加载。父类加载器采用同样的策略,首先查看自己的缓存,(如果仍然没有)则继续委托其父类加载去加载,一直到 BootStrapClassLoader(启动类加载器)。
