ClassLoader 层次结构与自定义加载器
理解引导、平台和应用程序类加载器,并编写自定义 ClassLoader
ClassLoader 层次结构与自定义加载器 是 CoddyKit 上的免费 Java Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
ClassLoader 层次结构
JVM 使用 ClassLoader 层次结构。每个加载器都有一个父加载器;在自行加载类之前,它会先委托给父加载器(父加载器优先委托模型)。
引导 ClassLoader
引导 ClassLoader 会加载核心 JDK 类(java.lang.*、java.util.*)。它使用本机代码实现,没有 Java 父加载器;getParent() 返回 null。
ClassLoader cl = String.class.getClassLoader();
System.out.println(cl); // null (bootstrap ClassLoader)平台 ClassLoader(Java 9 及更高版本)
平台 ClassLoader(以前称为扩展 ClassLoader)会加载 JDK 中不属于引导加载集合的模块(java.sql、java.xml 等)。它的父加载器是引导加载器。
ClassLoader platform = ClassLoader.getPlatformClassLoader();
System.out.println(platform.getClass().getName());
// jdk.internal.loader.ClassLoaders$PlatformClassLoader应用程序(系统)ClassLoader
应用程序 ClassLoader 会从类路径(-cp / CLASSPATH)加载应用程序类。它的父加载器是平台 ClassLoader,也是用户代码的默认加载器。
ClassLoader app = ClassLoader.getSystemClassLoader();
System.out.println(app.getClass().getName());
// jdk.internal.loader.ClassLoaders$AppClassLoader父加载器优先委托
加载 com.example.MyService 时,AppClassLoader 会先询问它的父加载器(平台加载器),平台加载器再询问引导加载器。只有当所有父加载器都无法加载该类时,子加载器才会尝试自行加载。
类身份与 ClassLoader
由不同 ClassLoader 加载的同名类会被视为不同类型。在它们之间进行类型转换会抛出 ClassCastException——这在插件系统和 OSGi 中非常重要。
// Loaded by two different loaders → different Class objects
Class<?> c1 = loader1.loadClass("com.example.Plugin");
Class<?> c2 = loader2.loadClass("com.example.Plugin");
System.out.println(c1 == c2); // false!编写自定义 ClassLoader
继承 ClassLoader 并重写 findClass(String name)。从自定义来源(加密 JAR、网络或数据库)读取字节码,然后调用 defineClass。
public class EncryptedClassLoader extends ClassLoader {
public EncryptedClassLoader(ClassLoader parent) { super(parent); }
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes = decrypt(readBytecodeFromVault(name));
return defineClass(name, bytes, 0, bytes.length);
}
}URL ClassLoader:从 JAR 加载
URLClassLoader 会从 URL 列表(文件路径或 HTTP URL)加载类。它适用于在运行时添加 JAR 的插件系统。
URL[] urls = { new File("plugins/my-plugin.jar").toURI().toURL() };
try (URLClassLoader loader = new URLClassLoader(urls, getClass().getClassLoader())) {
Class<?> cls = loader.loadClass("com.example.PluginImpl");
Plugin plugin = (Plugin) cls.getDeclaredConstructor().newInstance();
plugin.start();
}关闭 ClassLoader
完成后务必关闭 URLClassLoader——它会使 JAR 保持打开状态。关闭它后,便可以删除或更新 JAR。请使用自动资源管理语法。
子加载器优先委托(隔离加载)
某些容器(Tomcat、Spring Boot 包含依赖的 JAR)会反转层次结构:子加载器先尝试加载,只有找不到时才回退到父加载器。这可以隔离不同 Web 应用程序之间的库版本。
ClassLoader 泄漏
只有在没有任何由某个类加载器加载的类仍可访问时,该类加载器才会被垃圾回收。持有已加载类中对象的静态字段会使加载器保持存活——这在重新部署场景中是常见的泄漏原因。
快速检查
ClassLoader 在尝试自行加载类之前会做什么?
回顾
三级层次结构:引导加载器 → 平台加载器 → 应用程序加载器。父加载器优先委托可以防止类重复。自定义加载器会重写 findClass。插件系统使用 URLClassLoader。关闭加载器可以防止泄漏。
常见问题解答
「ClassLoader 层次结构与自定义加载器」课时是免费的吗?
是的 — 「ClassLoader 层次结构与自定义加载器」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「ClassLoader 层次结构与自定义加载器」这节课中我会学到什么?
理解引导、平台和应用程序类加载器,并编写自定义 ClassLoader 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「ClassLoader 层次结构与自定义加载器」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 类加载阶段:加载、链接、初始化
- ClassLoader 层次结构与自定义加载器
- 使用 javap 检查字节码
- 即时编译与分层编译