双亲委派模型详解
一、类加载过程
类从加载到虚拟机到卸载,经历以下阶段:
加载
将.class文件加载到内存,创建Class对象。
加载方式:
- 从本地文件系统加载
- 从网络获取
- 从zip包读取
- 运行时计算生成
连接
验证:
- 文件格式验证
- 元数据验证
- 字节码验证
- 符号引用验证
准备:为类变量分配内存并设置初始值。
解析:将符号引用替换为直接引用。
初始化
执行类构造器
二、类加载器
启动类加载器
Bootstrap ClassLoader,负责加载Java核心类库。
加载路径:
- JAVA_HOME/lib/rt.jar
- JAVA_HOME/lib/resources.jar
- JAVA_HOME/lib/sunrt.jar
扩展类加载器
Extension ClassLoader,负责加载扩展类库。
加载路径:
- JAVA_HOME/lib/ext目录
应用类加载器
Application ClassLoader,负责加载用户类路径上的类。
加载路径:
- classpath路径
自定义类加载器
继承ClassLoader类,实现findClass方法。
用途:
- 从非标准来源加载类
- 实现类隔离
- 实现热部署
三、双亲委派模型
模型结构
类加载器之间的父子关系:
1 | 启动类加载器 |
工作流程
类加载器收到加载请求时:
- 委托父类加载器加载
- 父类加载器无法加载时,自己尝试加载
优势
安全性:
- 核心类库不会被自定义类覆盖
- 防止恶意代码替换核心类
一致性:
- 同一个类由同一个加载器加载
- 避免类重复加载
四、双亲委派的实现
ClassLoader的loadClass方法:
1 | protected Class<?> loadClass(String name, boolean resolve) { |
五、打破双亲委派模型
何时需要打破
- 需要加载不同版本的同名类
- 实现类的隔离和热部署
- SPI机制(JDBC等)
实现方式
重写loadClass方法,不委托父加载器:
1 |
|
线程上下文类加载器
SPI机制使用线程上下文类加载器加载接口实现类:
1 | Thread.currentThread().getContextClassLoader() |
六、Tomcat类加载机制
Tomcat自定义类加载器实现Web应用隔离:
1 | CommonClassLoader:共享类库 |
优势:
- Web应用之间类隔离
- 支持不同版本的同名类
- 支持热部署
七、总结
类加载机制要点:
- 类加载过程:加载、连接、初始化
- 三层类加载器:启动、扩展、应用
- 双亲委派模型保证安全性和一致性
- 特殊场景可打破双亲委派
理解类加载机制有助于解决类冲突、实现模块化和热部署。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 夏天的风吹向哪里!
