文章内容收录到个人网站,方便阅读:hardyfish.top/
资料分享
Java虚拟机规范.Java SE 8版:
- 资料链接:url81.ctfile.com/f/57345181-…
- 访问密码:3899
深入理解Java虚拟机:JVM高级特性与最佳实践(第3版):
- 资料链接:url81.ctfile.com/f/57345181-…
- 访问密码:3899
1. 类加载器简介
JVM 采用类加载器(ClassLoader) 来动态加载 .class 文件。从 JVM 角度来看,类加载器分为两类:
- 启动类加载器(Bootstrap ClassLoader) :用 C++ 实现,属于 JVM 本身的一部分。
- 其他 Java 实现的类加载器:继承自
java.lang.ClassLoader,用于加载应用程序类。
2. JDK 1.8 及之前的类加载器
在 JDK 1.8 及之前,Java 使用 3 种默认类加载器:
| 类加载器 | 实现类 | 作用 |
|---|---|---|
| 启动类加载器(Bootstrap ClassLoader) | C++ 实现 | 加载 JAVA_HOME/lib 目录下的核心类库(如 rt.jar) |
| 扩展类加载器(Extension ClassLoader) | sun.misc.Launcher$ExtClassLoader | 加载 JAVA_HOME/lib/ext 目录下的扩展类 |
| 应用类加载器(Application ClassLoader) | sun.misc.Launcher$AppClassLoader | 加载 classpath 目录下的应用类 |
3. JDK 1.9 之后的类加载器变化
JDK 1.9 引入 Jigsaw 模块化系统(Project Jigsaw) ,对类加载器进行了调整:
| JDK 1.8 | JDK 1.9 及之后 | 变化 |
|---|---|---|
| 扩展类加载器(Extension ClassLoader) | 平台类加载器(Platform ClassLoader) | 负责加载 JDK 模块化系统中的非核心模块 |
| 应用类加载器(Application ClassLoader) | 应用类加载器(Application ClassLoader) | 负责加载应用程序的 classpath |
新的 Platform ClassLoader(平台类加载器)
-
JDK 1.9 之后,扩展类加载器被移除,改为 Platform ClassLoader。
-
Platform ClassLoader 作用
:
- 负责加载 JDK 平台 API 的非核心模块(如
java.sql)。 - 不能直接访问
java.base模块(由Bootstrap ClassLoader加载)。 - 无法直接访问
classpath,但可以通过ModuleLayer访问。
- 负责加载 JDK 平台 API 的非核心模块(如
4. JDK 1.8 vs JDK 1.9 类加载器结构
JDK 1.8 类加载器结构
plaintext
Bootstrap ClassLoader
├── Extension ClassLoader
│ ├── 加载 JAVA_HOME/lib/ext 目录
├── Application ClassLoader
├── 加载 classpath 目录
├── 自定义类加载器(User-defined ClassLoader)
JDK 1.9 类加载器结构
plaintext
Bootstrap ClassLoader
├── Platform ClassLoader (JDK 9+ 新增)
│ ├── 加载 JDK 平台模块(如 java.sql)
├── Application ClassLoader
├── 加载 classpath 目录
├── 自定义类加载器(User-defined ClassLoader)
5. 类加载器的继承关系
类加载器并不是继承关系,而是 组合关系,即父类加载器是一个 ClassLoader 类型的成员变量:
java
public abstract class ClassLoader {
private final ClassLoader parent; // 组合关系
}
在 ClassLoader 内部,如果找不到类,会委派给 parent 继续查找:
java
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class<?> c = findLoadedClass(name);
if (c == null) {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
}
return c;
}
6. 关键变化总结
| JDK 版本 | 主要类加载器 | 变化 |
|---|---|---|
| JDK 1.8 及之前 | Bootstrap、Extension、Application | 使用 Extension ClassLoader 加载 lib/ext |
| JDK 1.9 及之后 | Bootstrap、Platform、Application | Extension ClassLoader 被 Platform ClassLoader 取代 |
7. 影响
-
模块化影响类加载
- JDK 1.9 之后,类被封装在
module-info.java中,非公开模块不能被直接访问。
- JDK 1.9 之后,类被封装在
-
Platform ClassLoader 只能加载特定的 JDK 模块
- 不能直接加载
classpath中的类。
- 不能直接加载
-
自定义类加载器仍然适用
- 但需要在模块化环境下遵循新的访问规则。
8. 结论
- JDK 1.9 之后,Platform ClassLoader 替代了 Extension ClassLoader。
- 类加载器仍然遵循双亲委派模型,但模块化影响了类加载机制。
- 自定义类加载器仍然适用,但需要遵循模块化规则。