7. JVM类加载器与双亲委派模型
1. 类加载器
类加载器是Java虚拟机(JVM)的重要组成部分,负责将.class文件(字节码文件)加载到JVM中,并转换为java.lang.Class类的实例。
Java中的类加载器类型
1. 启动类加载器(Bootstrap ClassLoader)
由C++实现,是JVM的一部分
负责加载Java核心类库(
<JAVA_HOME>/jre/lib
目录下的类)是其他所有类加载器的父加载器
唯一没有父类的加载器
2. 扩展类加载器(Extension ClassLoader)
由Java实现(
sun.misc.Launcher$ExtClassLoader
)负责加载
<JAVA_HOME>/jre/lib/ext
目录下的类是应用类加载器的父加载器
3. 应用类加载器(Application ClassLoader/System ClassLoader)
由Java实现(
sun.misc.Launcher$AppClassLoader
)负责加载用户类路径(ClassPath)上的类库
是程序中默认的类加载器
4. 自定义类加载器
开发者可以继承java.lang.ClassLoader
类,实现自己的类加载器,用于特殊需求如:
热部署
代码加密
从非标准位置加载类
在Java的不同版本中,
<JAVA_HOME>/lib
和<JAVA_HOME>/jre/lib
的关系有所变化:Java 8 及之前版本根目录下包含 jre 目录。
Java 9 及之后版本根目录下不在包含 jre 目录,而是对其进行了合并统一。
2. 双亲委派模型
双亲委派模型是Java类加载器(ClassLoader)在加载类时遵循的一种工作机制,它是Java安全性和稳定性的重要保障。
核心原理
自底向上检查:当一个类加载器收到类加载请求时,它首先不会自己尝试加载,而是将这个请求委托给父类加载器去完成。
自顶向下尝试:只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
工作流程
当前类加载器首先检查请求的类是否已经被加载过
如果没有,则将加载任务委托给父类加载器
父类加载器同样遵循这个委托流程,直到启动类加载器(Bootstrap ClassLoader)
如果父类加载器无法完成加载(抛出ClassNotFoundException),则由当前类加载器尝试加载
如果当前类加载器也无法加载,则抛出ClassNotFoundException
优点
安全性:防止核心API被篡改(例如用户自定义的java.lang.String类不会被加载)
避免重复加载:同一个类只会被一个类加载器加载一次
稳定性:保证Java核心库的类型安全
3. 总结
3.1 什么是类加载器?
JVM只会运行二进制文件,类加载器的作用就是将字节码文件加载到JVM中,从而让Java程序能够启动起来。
3.2 类加载器有哪些?
- 启动类加载器(BootStrap ClassLoader):加载JAVA HOME/jre/lib目录下的库
- 扩展类加载器(ExtClassLoader):主要加载JAVA HOME/jre/lib/ext目录中的类
- 应用类加载器(AppClassLoader):用于加载classPath下的类
- 自定义类加载器(CustomizeClassLoader):自定义类继承ClassLoader,实现自定义类加载规则。
3.3 什么是双亲委派模型?
加载某一个类,先委托上一级的加载器进行加载,如果上级加载器也有上级,则会继续向上委托,如果该类委托上级没有被加载,子加载器尝试加载该类。
3.4 JVM为什么采用双亲委派机制?
- 通过双亲委派机制可以避免某一个类被重复加载,当父类已经加载后则无需重复加载,保证唯一性。
- 为了安全,保证类库API不会被修改
上一篇 下一篇