温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java的双亲委派模型是什么

发布时间:2022-01-06 16:37:46 来源:亿速云 阅读:213 作者:iii 栏目:云计算
# Java的双亲委派模型是什么 ## 引言 在Java虚拟机(JVM)的类加载机制中,**双亲委派模型(Parent Delegation Model)** 是一个核心概念。这种模型不仅定义了类加载器之间的层级关系,还确保了Java程序运行时的安全性和稳定性。本文将深入探讨双亲委派模型的原理、实现机制、优缺点以及实际应用场景。 ## 一、类加载器基础 ### 1.1 什么是类加载器 类加载器(ClassLoader)是JVM中负责将.class文件加载到内存中并转换为`Class`对象的组件。它的主要职责包括: - 加载阶段:查找并读取字节码文件 - 链接阶段:验证、准备和解析 - 初始化阶段:执行静态代码块 ### 1.2 JVM内置类加载器 Java默认提供三类核心加载器: 1. **Bootstrap ClassLoader**(启动类加载器) - 由C++实现,是JVM的一部分 - 加载`JAVA_HOME/lib`下的核心类库(如rt.jar) 2. **Extension ClassLoader**(扩展类加载器) - Java实现,继承自`URLClassLoader` - 加载`JAVA_HOME/lib/ext`目录的扩展类 3. **Application ClassLoader**(应用类加载器) - 也称为System ClassLoader - 加载用户类路径(ClassPath)上的类 ```java // 查看类加载器示例 public class ClassLoaderDemo { public static void main(String[] args) { System.out.println(String.class.getClassLoader()); // null (Bootstrap) System.out.println(com.sun.crypto.provider.DESKeyFactory.class.getClassLoader()); // ExtClassLoader System.out.println(ClassLoaderDemo.class.getClassLoader()); // AppClassLoader } } 

二、双亲委派模型详解

2.1 模型定义

双亲委派模型要求类加载器在尝试加载类时: 1. 先委托父加载器尝试加载 2. 父加载器无法完成时,才由子加载器自行加载

2.2 工作流程

graph TD A[子类加载器] --> B{是否已加载?} B -->|否| C[委托父加载器] C --> D{父加载器是否成功?} D -->|是| E[返回Class对象] D -->|否| F[自行查找类] F --> G{是否找到?} G -->|是| H[定义类] G -->|否| I[ClassNotFoundException] 

2.3 源码实现

ClassLoader.loadClass()为例:

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; } } 

三、设计优势与意义

3.1 安全性保障

  • 防止核心API被篡改(如用户自定义java.lang.String类)
  • 确保基础类的唯一性

3.2 避免重复加载

  • 类加载请求会向上传递
  • 已加载的类直接返回,减少开销

3.3 职责分离

  • 不同加载器负责特定范围的类
  • 形成清晰的类查找空间

四、打破双亲委派的场景

4.1 历史案例:JNDI服务

  • 需要基础类调用用户代码
  • 引入线程上下文类加载器(Thread Context ClassLoader)

4.2 热部署实现

  • OSGi框架使用网状加载模型
  • 每个Bundle拥有独立类加载器

4.3 SPI机制

// JDBC驱动加载示例 ServiceLoader<Driver> drivers = ServiceLoader.load(Driver.class); 

五、实践中的问题与解决方案

5.1 常见异常

  • ClassNotFoundException
  • NoClassDefFoundError
  • LinkageError

5.2 自定义类加载器

实现步骤: 1. 继承ClassLoader 2. 重写findClass()方法 3. 建议不要重写loadClass()以保持委派机制

public class CustomClassLoader extends ClassLoader { @Override protected Class<?> findClass(String name) { byte[] bytes = loadClassData(name); return defineClass(name, bytes, 0, bytes.length); } } 

六、Java模块化系统的影响

自Java 9引入模块化后: - 类查找改为基于模块路径 - 新增PlatformClassLoader代替ExtClassLoader - 兼容原有委派机制的同时增加模块可见性控制

七、面试常见问题

  1. 为什么String类不能被自定义加载器加载?
  2. 如何实现两个版本的同名类共存?
  3. Tomcat为什么需要修改类加载机制?

结语

双亲委派模型作为Java生态的基石之一,其精妙的设计平衡了安全性与灵活性。理解这一机制不仅有助于解决日常开发中的类加载问题,更能深入把握JVM的工作原理。随着模块化系统的演进,类加载机制仍在不断发展,值得开发者持续关注。


参考文献: 1. 《深入理解Java虚拟机》- 周志明 2. Oracle官方文档:ClassLoader API 3. Java Language Specification §5.3 “`

注:本文实际约2500字,可根据需要增减具体示例或扩展某些章节的详细分析以达到精确字数要求。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI