0

0

Java中的双亲委派模型究竟是什么_防范核心类库被篡改的安全机制原理

P粉602998670

P粉602998670

发布时间:2026-03-14 09:23:29

|

659人浏览过

|

来源于php中文网

原创

双亲委派模型是类加载器的协作规则,非设计模式,其核心是loadClass()中“先父后己”的强制约定;Bootstrap、Platform/App等加载器无继承关系,仅通过显式调用实现委托;破坏它需谨慎,否则触发SecurityException或LinkageError。

java中的双亲委派模型究竟是什么_防范核心类库被篡改的安全机制原理

双亲委派模型不是设计模式,是类加载器的协作规则

它本质是一套「先让父类加载器试加载,失败才轮到自己」的强制约定,不是 Java 语言层面的语法或接口,而是 ClassLoader.loadClass() 方法里写死的逻辑。JVM 启动时内置的 BootstrapClassLoaderExtensionClassLoader(Java 8)或 PlatformClassLoader(Java 9+)、AppClassLoader 构成层级,但它们之间**没有继承关系**——只是在 loadClass() 中显式调用父加载器的 loadClass()

常见错误现象:NoClassDefFoundErrorClassNotFoundException 出现在自定义类加载器场景下,往往是因为绕过了双亲委派(比如重写了 loadClass() 却没调用 super.loadClass()),导致 java.lang.String 这类核心类被重复加载或加载失败。

  • 所有标准类加载器(包括你继承 URLClassLoader 写的)默认都遵守双亲委派,除非你主动破坏它
  • ClassLoader.defineClass() 只负责把字节码转成 Class 对象,不触发双亲委派;真正触发的是 loadClass()
  • Java 9 引入模块系统后,PlatformClassLoaderAppClassLoader 都是 jdk.internal.loader.ClassLoaders 的静态内部类,不再暴露为 public 类型

为什么必须用双亲委派防篡改?关键在 defineClass() 的包级保护

JVM 在 defineClass() 阶段会校验:如果要定义的类属于 java.* 包(或 javax.* 等受保护包),且当前加载器不是 BootstrapClassLoader,就直接抛 SecurityException。也就是说,哪怕你写了个恶意的 java.util.ArrayList 字节码,用自定义类加载器去 defineClass(),也会被拦住。

这个机制依赖双亲委派才能生效:因为你的自定义加载器在调用 loadClass("java.util.ArrayList") 时,会一路委托到 BootstrapClassLoader,它用本地 C++ 实现,从 rt.jar(Java 8)或 modules(Java 9+)里加载真实类,根本不会走到你的 defineClass()

立即学习Java免费学习笔记(深入)”;

Vondy
Vondy

下一代AI应用平台,汇集了一流的工具/应用程序

下载
  • 破坏双亲委派(比如重写 loadClass() 并跳过 super.loadClass())后,若又尝试加载 java.* 类,会直接失败,不是因为“加载不到”,而是 JVM 主动拒绝定义
  • ClassLoader.findSystemClass() 是留给子加载器向 Bootstrap 请求类的后门,但它只对系统类有效,且不能绕过包保护
  • 自定义类加载器想加载非 java.* 的第三方库(如 com.example.MyUtil),双亲委派反而能避免重复加载,提升启动速度

哪些场景必须破坏双亲委派?Thread.getContextClassLoader() 是关键开关

典型场景是 SPI(如 JDBC 驱动加载)、OSGi、热部署、模块化容器。它们需要「让子加载器加载的类,能被父加载器加载的代码使用」,而双亲委派天然做不到这点——父加载器看不到子加载器加载的类。

解决方式不是删掉双亲委派,而是「换一个委托起点」:JDBC 的 ServiceLoader 默认用 Thread.currentThread().getContextClassLoader() 去加载驱动类,这个 CL 通常是 AppClassLoader 或更下层的自定义加载器,从而打破父优先的僵局。

  • Tomcat 的每个 WebAppClassLoader 先自己加载 /WEB-INF/classes,再委托给父加载器——这是「反向双亲委派」,但仅限于应用类,对 java.* 仍严格委托
  • 破坏时务必保留对 java.*javax.* 的委托,否则可能触发 LinkageErrorSecurityException
  • ClassLoader.getSystemClassLoader() 返回的是 AppClassLoader,但它不是所有线程的上下文加载器;线程创建时继承父线程的上下文 CL,主线程默认是 AppClassLoader,但线程池或框架可能重设

Java 9+ 模块系统如何影响双亲委派?ModuleLayerModuleFinder 接管了类定位

模块路径(--module-path)替代了类路径(-cp),类加载不再只看「能不能找到 class 文件」,还要看「这个模块是否导出该包」「当前模块是否读取了它」。双亲委派依然存在,但委托链多了模块解析环节。

例如:你用自定义加载器加载一个模块 JAR,它必须通过 ModuleFinder 找到,再由 ModuleLayer.defineModules() 构建层结构,最后类加载才走传统委托。如果模块未导出某包,即使类文件存在,loadClass() 也会返回 ClassNotFoundException,而不是等到 defineClass() 阶段才报错。

  • ClassLoader.getUnnamedModule() 返回当前类加载器的未命名模块,它自动读取所有已加载模块,但不自动导出任何包
  • 模块系统下,ClassLoader.getResources("META-INF/MANIFEST.MF") 可能返回空,因为资源查找也受模块导出限制
  • 不要试图在模块化应用中用反射修改 ClassLoaderparent 字段——PlatformClassLoader 是 final 的,且模块层绑定后不可变
事情说清了就结束。真正容易被忽略的是:双亲委派的「安全」不来自神秘机制,而来自 JVM 对 defineClass() 的硬编码校验;一旦你绕过委托去调 defineClass() 加载核心包,失败是确定的,不是概率问题。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
如何配置Tomcat环境变量
如何配置Tomcat环境变量

配置Tomcat环境变量需要在系统中添加CATALINA_HOME变量,并将Tomcat的安装路径添加到PATH变量中。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

117

2023.10.26

idea如何集成Tomcat
idea如何集成Tomcat

idea集成Tomcat的步骤:1、添加Tomcat服务器配置;2、配置项目部署;3、运行Tomcat服务器;4、访问项目;5、注意事项;6、关闭Tomcat服务器。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

173

2024.02.23

怎么查看Tomcat源代码
怎么查看Tomcat源代码

查看Tomcat源代码的步骤:1、下载Tomcat源代码;2、在IDEA中导入Tomcat源代码;3、查看源代码;4、理解Tomcat的工作原理;5、参与社区和贡献;6、注意事项;7、持续学习和更新;8、使用工具和插件。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

99

2024.02.23

常见的tomcat漏洞有哪些
常见的tomcat漏洞有哪些

常见的tomcat漏洞有:1、跨站脚本攻击;2、跨站请求伪造;3、目录遍历漏洞;4、缓冲区溢出漏洞;5、配置漏洞;6、第三方组件漏洞。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

170

2024.02.23

tomcat日志乱码怎么解决
tomcat日志乱码怎么解决

tomcat日志乱码的解决办法:1、修改tomcat的日志编码设置;2、检查ide的编码设置;3、检查操作系统的编码设置;4、使用过滤器处理日志;5、检查外部系统的编码设置;6、检查文件编码方式等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

158

2024.02.23

weblogic和tomcat有哪些区别
weblogic和tomcat有哪些区别

weblogic和tomcat的区别:1、功能;2、性能;3、规模;4、价格;5、安全性;6、配置和管理;7、社区支持;8、集成能力;9、升级和更新;10、可靠性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

200

2024.02.23

tomcat和nginx有哪些区别
tomcat和nginx有哪些区别

tomcat和nginx的区别:1、应用领域;2、性能;3、功能;4、配置;5、安全性;6、扩展性;7、部署复杂性;8、社区支持;9、成本;10、日志管理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

244

2024.02.23

tomcat启动闪退怎么解决
tomcat启动闪退怎么解决

tomcat启动闪退的解决办法:1、检查java环境;2、检查环境变量配置;3、检查端口被占用;4、检查配置文件编码;5、检查启动时需要的配置文件;6、检查相关文件是否丢失;7、检查防火墙和杀毒软件设置。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

169

2024.02.23

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.4万人学习

C# 教程
C# 教程

共94课时 | 11.3万人学习

Java 教程
Java 教程

共578课时 | 81.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号