跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
双亲委派模型
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{Note|本文详细讲解JVM类加载机制中的'''双亲委派模型'''(Parent Delegation Model),涵盖其核心原理、工作流程、代码示例及实际应用场景。}} == 概述 == '''双亲委派模型'''是Java虚拟机(JVM)在类加载阶段采用的一种层次化责任分配机制。其核心思想是:当一个类加载器收到类加载请求时,首先将请求委派给父类加载器处理,仅当父类加载器无法完成加载时,子类加载器才会尝试自行加载。这种模型通过层级关系避免了类的重复加载,并保障了Java核心库的安全性。 == 核心原理 == 双亲委派模型通过以下三个核心类加载器实现层级关系: * '''启动类加载器(Bootstrap ClassLoader)''':加载JRE核心库(如<code>rt.jar</code>),由C++实现,无Java对应类。 * '''扩展类加载器(Extension ClassLoader)''':加载<code>jre/lib/ext</code>目录下的扩展类。 * '''应用程序类加载器(Application ClassLoader)''':加载用户类路径(ClassPath)下的类。 === 层级关系图 === <mermaid> flowchart TD A[自定义类加载器] --> B[应用程序类加载器] B --> C[扩展类加载器] C --> D[启动类加载器] </mermaid> == 工作流程 == 双亲委派模型的类加载流程如下: # 子类加载器收到类加载请求。 # 检查是否已加载该类,若已加载则直接返回。 # 若未加载,委派请求给父类加载器。 # 父类加载器递归执行相同逻辑,直到启动类加载器。 # 若父类加载器无法完成加载,子类加载器调用<code>findClass()</code>方法尝试加载。 === 伪代码实现 === <syntaxhighlight lang="java"> protected Class<?> loadClass(String name, boolean resolve) { synchronized (getClassLoadingLock(name)) { // 1. 检查是否已加载 Class<?> c = findLoadedClass(name); if (c == null) { try { // 2. 委派给父类加载器 if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) {} // 3. 父类无法加载时自行加载 if (c == null) { c = findClass(name); } } return c; } } </syntaxhighlight> == 实际案例 == === 案例1:避免核心类被篡改 === 若用户自定义一个<code>java.lang.String</code>类并尝试加载,由于双亲委派机制会优先委派给启动类加载器加载核心库中的<code>String</code>,自定义类将不会被加载,从而保证核心库的安全性。 === 案例2:Tomcat的类加载优化 === Tomcat为每个Web应用提供独立的<code>WebappClassLoader</code>,但打破了双亲委派模型: * 先尝试自行加载(如Web应用内的类)。 * 失败后再委派给父类加载器。 * 实现了应用间类的隔离。 == 打破双亲委派的情况 == 以下场景需打破双亲委派模型: * '''SPI机制'''(如JDBC驱动加载):通过线程上下文类加载器(<code>Thread.currentThread().getContextClassLoader()</code>)实现。 * '''热部署''':如OSGi框架通过网状类加载器结构实现模块化。 == 数学表示 == 类加载过程可形式化为: <math> \text{loadClass}(C) = \begin{cases} \text{findLoadedClass}(C) & \text{if } C \text{ is loaded} \\ \text{parent.loadClass}(C) & \text{if parent exists} \\ \text{findClass}(C) & \text{otherwise} \end{cases} </math> == 常见问题 == {{Q&A |问题1 = 双亲委派模型是否必须遵守? |答案1 = 不是。开发者可通过重写<code>loadClass()</code>方法打破该模型,但需谨慎处理安全性问题。 |问题2 = 如何自定义类加载器? |答案2 = 继承<code>ClassLoader</code>并重写<code>findClass()</code>方法,避免直接修改<code>loadClass()</code>逻辑。 }} == 总结 == 双亲委派模型通过层级委派机制实现了类的唯一性保护和核心库安全隔离,是JVM类加载体系的基石。理解其原理有助于解决类冲突、实现热部署等高级特性。 [[Category:计算机科学]] [[Category:面试技巧]] [[Category:JVM相关]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
该页面使用的模板:
模板:Note
(
编辑
)
模板:Q&A
(
编辑
)