双亲委派模型通过分层职责、TCCL、模块化和自定义加载器实现安全扩展:启动类加载器管java.,平台类加载器管javax.及标准模块,应用类加载器管用户代码;TCCL提供SPI动态加载通道;模块系统强化委派策略;自定义加载器仅重写findClass并指定父加载器,确保委派链不变。

双亲委派模型本身是为保障安全与一致性而设计的,看似严格,但恰恰在基础库扩展时提供了可控的灵活性——不是靠打破它,而是通过分层职责和标准接口,在不牺牲核心稳定性的前提下支持扩展。
类加载器分层天然支持扩展边界
启动类加载器只管 java.*,扩展类加载器(Platform ClassLoader)负责 javax.* 和平台模块(如 java.sql、java.xml),应用类加载器则专注用户代码。这种分工意味着:
- 新增基础功能(比如一个新标准 API 模块)可直接放入
JAVA_HOME/lib或模块路径,由平台加载器自动识别,无需修改任何应用代码 - 厂商或框架提供的扩展(如 JDBC 驱动、JAXP 实现)可放在
lib/ext或通过--module-path加载,它们被平台层统一管理,对应用透明 - 用户升级 JDK 后,只要遵循模块声明和导出规则,原有扩展仍能被正确委派加载,兼容性有保障
线程上下文类加载器(TCCL)提供扩展钩子
当基础库需要动态加载用户提供的实现(例如 SPI 机制中的 ServiceLoader),它不能依赖当前类的加载器(可能是 Bootstrap 或 Platform),而需借助 TCCL:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
-
ServiceLoader.load(Service.class)内部会调用Thread.currentThread().getContextClassLoader() - 应用启动时通常将 AppClassLoader 设为 TCCL,这样基础库就能“向下”加载用户自定义的实现类
- 这是对双亲委派的补充而非破坏:委派链保持不变,只是在需要时引入一条“反向信任通道”
模块系统(Jigsaw)强化了扩展语义
JDK 9+ 的模块化不是绕过双亲委派,而是将其升级为更精细的委派策略:
立即学习“Java免费学习笔记(深入)”;
- 每个模块声明
requires和exports,类加载器按模块依赖图决定是否委派、向谁委派 - 可通过
--add-opens或addReads在运行时动态放宽封装限制,让扩展库能访问内部 API(需明确授权) - 平台模块(如
java.base)仍由 Bootstrap 加载,但用户模块可独立编译、部署、升级,基础库只需面向接口编程
自定义加载器在扩展点上保持委派契约
若需加载加密字节码、远程类或热更新类,自定义类加载器应继承 ClassLoader 并重写 findClass,但必须保留 loadClass 的默认逻辑:
- 不重写
loadClass,确保委派行为不变;只覆盖findClass去定义“自己怎么找字节码” - 构造时显式指定父加载器(如
super(ClassLoader.getSystemClassLoader())),保证核心类仍走标准路径 - 这样既支持特殊加载逻辑,又不干扰
String、ArrayList等基础类的加载一致性

















