Java 中的类加载器的双亲委派模型:原理、层级与实现

Java 中的类加载器的双亲委派模型:原理、层级与实现

类加载器的双亲委派模型(Parents Delegation Model)是Java 虚拟机(JVM)中类加载器协同工作的核心设计原则 ,它定义了类加载器之间的层级关系类加载请求的传递规则,是 JVM 保证类加载安全性、避免类重复加载的关键机制。

一、核心定义

一个类加载器在接收到类加载请求 时,不会立即自己尝试加载该类 ,而是先将加载请求向上委派给它的父类加载器 处理;父类加载器会重复这一委派行为,直到请求传递到顶层的启动类加载器 ;只有当父类加载器在自己的类搜索范围内无法找到该类(加载失败) 时,子加载器才会尝试自己去加载这个类。

简单来说:先父后子,父能则父加载,父不能则子加载

二、Java 默认的类加载器层级(自上而下)

JVM 提供了 3 个核心的内置类加载器,严格遵循双亲委派的层级关系,下层加载器均以上层加载器为 "父加载器"(注:此处的父子并非继承关系,而是组合关系,子加载器持有父加载器的引用):

1.启动类加载器(Bootstrap ClassLoader)

顶层加载器,由C/C++ 实现(并非 Java 类),属于 JVM 内核的一部分;

负责加载 Java 核心类库,对应路径为JAVA_HOME/jre/lib(如rt.jarcore.jar,包含java.langjava.util等核心包);

该加载器没有父加载器,是委派链的终点。

2.扩展类加载器(Extension ClassLoader)

由 Java 实现(sun.misc.Launcher$ExtClassLoader),父加载器为启动类加载器;

负责加载 Java 扩展类库,对应路径为JAVA_HOME/jre/lib/ext,或系统属性java.ext.dirs指定的目录;

加载启动类加载器未覆盖的扩展功能类。

3.应用程序类加载器(Application ClassLoader)

由 Java 实现(sun.misc.Launcher$AppClassLoader),父加载器为扩展类加载器;

也叫系统类加载器 ,是程序运行时默认的类加载器

负责加载用户自定义的类 和项目依赖的第三方类库,对应路径为系统属性java.class.path(即我们常说的classpath)。

4.简单图解:

三、双亲委派模型的核心作用(设计意义)

该模型的设计完全围绕JVM 的类加载安全类的唯一性,核心作用有两点:

  1. 保证 Java 核心类的安全性,防止核心 API 被篡改

    核心类(如java.lang.Stringjava.lang.Object)只能由启动类加载器 加载,若用户自定义一个同名的java.lang.String类,由于双亲委派规则,加载请求会先委派到启动类加载器,而启动类加载器已加载过核心的String类,用户自定义的同名类不会被加载,避免了恶意代码篡改核心 API 的风险。

  2. 保证类的唯一性,避免类重复加载

    同一个类(全限定类名,如com.example.Demo)只会被委派链中第一个能加载它的类加载器 加载,后续所有子加载器都会直接使用父加载器加载的类实例,避免了同一个类在 JVM 中被多次加载形成不同的类对象(JVM 中,类的唯一性由 "类加载器 + 全限定类名" 共同决定)。

四、双亲委派模型的通用标准工作流程

无论接收加载请求的是应用程序类加载器(默认)还是自定义类加载器,均遵循以下 6 步核心流程(自定义类加载器的父加载器为应用程序类加载器,流程仅多一层委派,核心逻辑一致):

  1. 接收请求:某类加载器(如应用程序类加载器)接收到加载指定类(全限定名)的请求;

  2. 向上委派 :该加载器不自行加载,立即将加载请求委派给自身的父类加载器

  3. 逐层传递 :父加载器重复「不自行加载,向上委派」的行为,直到请求传递到顶层的启动类加载器(委派链的终点,无父加载器);

  4. 顶层尝试加载:启动类加载器在自身专属加载路径( JAVA_HOME/jre/lib ,核心类库目录)中查找该类,尝试完成加载;

    • 若找到,直接加载该类,整个流程结束,后续无回退步骤;
    • 若未找到,加载失败,请求开始向下回退;
  5. 中层回退尝试:加载请求回退到启动类加载器的子加载器(扩展类加载器),扩展类加载器在自身加载路径( JAVA_HOME/jre/lib/ext 或 java.ext.dirs 指定目录)中查找该类,尝试完成加载;

    • 若找到,直接加载该类,流程结束;
    • 若未找到,加载失败,请求继续向下回退;
  6. 最终子加载器加载 :加载请求回退到最初接收请求的类加载器 ,该加载器在自身专属加载路径中查找并完成加载(若仍未找到,抛出ClassNotFoundException异常)。

核心规则提炼 :父加载器拥有绝对的加载优先权,只有当所有上层父加载器均无法加载时,子加载器才会执行「自行加载」的逻辑,全程无例外。

双亲委派模型的工作流程图:
找到,加载成功
未找到,加载失败
找到,加载成功
未找到,加载失败
找到,加载成功
未找到,加载失败

  1. 接收请求
    类加载器(应用/自定义)接收到类加载请求 2. 向上委派
    不自行加载,委派给自身父加载器 3. 逐层传递
    父加载器重复委派,直到顶层启动类加载器 4. 顶层尝试加载
    启动类加载器在JAVA_HOME/jre/lib查找 流程结束

类由启动类加载器完成加载
5. 中层回退尝试
扩展类加载器在JAVA_HOME/jre/lib/ext或java.ext.dirs查找 流程结束

类由扩展类加载器完成加载
6. 最终子加载器加载
回到最初接收请求的类加载器,在自身路径查找 流程结束

类由原加载器完成加载
抛出ClassNotFoundException异常

流程终止

五、典型场景案例:直观理解完整流程(加载用户自定义类)

加载用户自定义类com.example.MyDemo (存储在项目classpath下,属于应用程序类加载器的加载范围)为例,结合默认类加载器层级,还原每一步具体执行过程,更易理解:

  1. 程序触发com.example.MyDemo的加载,应用程序类加载器(系统默认加载器)接收到加载请求;
  2. 应用程序类加载器不自行加载,将请求委派给父加载器 ------ 扩展类加载器
  3. 扩展类加载器同样不自行加载,将请求委派给顶层父加载器 ------ 启动类加载器
  4. 启动类加载器在自身路径(JAVA_HOME/jre/lib)中查找com.example.MyDemo未找到,加载失败,请求回退;
  5. 加载请求回退到扩展类加载器,扩展类加载器在自身路径(JAVA_HOME/jre/lib/ext)中查找该类,未找到,加载失败,请求继续回退;
  6. 加载请求最终回退到应用程序类加载器,该加载器在自身路径(java.class.path,即项目classpath)中找到该类,完成加载,流程结束。
补充:核心类加载的简化流程(如java.lang.String

若加载的是 Java 核心类java.lang.String,流程会在第 4 步终止,无后续回退:

  1. 应用程序类加载器接收String加载请求,依次委派给扩展类加载器、启动类加载器;
  2. 启动类加载器在JAVA_HOME/jre/lib/rt.jar(核心类库)中找到String,直接完成加载,流程立即结束;
  3. 扩展类加载器和应用程序类加载器均不会再参与任何加载操作,这也是双亲委派保证核心类安全的关键。

五、补充:父子加载器的关系

很多人会误以为类加载器的 "父子" 是继承(extends) 关系,实际是组合(composition) 关系:

子加载器内部持有父加载器的引用,通过该引用实现加载请求的向上委派;

所有自定义类加载器的最终父加载器都是应用程序类加载器,形成统一的委派链。

总结

  1. 双亲委派模型是 JVM 类加载的核心原则:请求向上委派,加载向下回退
  2. 核心层级(自上而下):启动类加载器 → 扩展类加载器 → 应用程序类加载器;
  3. 核心价值:保证核心类安全(防止篡改) + 保证类唯一性(避免重复加载)
  4. 关键特性:父子加载器为组合关系(子持有父引用),非继承关系;
  5. 执行逻辑:父加载器优先尝试加载,仅当所有父加载器均加载失败时,子加载器才自行加载。
相关推荐
寻寻觅觅☆5 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
l1t5 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
青云计划6 小时前
知光项目知文发布模块
java·后端·spring·mybatis
赶路人儿6 小时前
Jsoniter(java版本)使用介绍
java·开发语言
ceclar1236 小时前
C++使用format
开发语言·c++·算法
探路者继续奋斗7 小时前
IDD意图驱动开发之意图规格说明书
java·规格说明书·开发规范·意图驱动开发·idd
码说AI7 小时前
python快速绘制走势图对比曲线
开发语言·python
Gofarlic_OMS7 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
星空下的月光影子7 小时前
易语言开发从入门到精通:补充篇·网络爬虫与自动化采集分析系统深度实战·HTTP/HTTPS请求·HTML/JSON解析·反爬策略·电商价格监控·新闻资讯采集
开发语言
老约家的可汗7 小时前
初识C++
开发语言·c++