Java类加载器层级需通过getClassLoader()和getParent()递归追溯,启动类加载器在Java层表现为null;JDK9+用PlatformClassLoader替代ExtClassLoader,String类在JDK9+由其加载。

Java 类加载器的层级关系不能直接“一键打印”,但可以通过代码逐级追溯其父子链路,核心是理解 getClassLoader() 和 getParent() 的配合使用,并注意启动类加载器在 Java 层表现为 null。
查看当前类的加载器链
每个类对象都可通过 .getClass().getClassLoader() 获取其加载器。该加载器的 getParent() 返回其父加载器,一直向上直到返回 null —— 这代表已到达 Bootstrap ClassLoader(由 C++ 实现,Java 层不可见)。
-
String.class.getClassLoader()返回null,因为String由启动类加载器加载 -
MyClass.class.getClassLoader()通常返回sun.misc.Launcher$AppClassLoader(JDK 8)或jdk.internal.loader.ClassLoaders$AppClassLoader(JDK 9+) -
Thread.currentThread().getContextClassLoader()常用于获取当前线程上下文加载器,多用于框架(如 Spring、JDBC)中跨类加载器场景
JDK 8 与 JDK 9+ 的结构差异
类加载器层级在 Java 9 模块化后发生重要变化:
- JDK 8 及之前:Bootstrap → ExtClassLoader → AppClassLoader
- JDK 9 起:
ExtClassLoader被移除;PlatformClassLoader取代其位置,作为AppClassLoader的父加载器,且其getParent()为null -
String.class.getClassLoader()在 JDK 9+ 中返回PlatformClassLoader(而非null),体现模块化对核心类归属的调整
用代码递归打印完整委托链
写一个通用工具方法,传入任意类,输出从该类加载器开始、逐级向上直到 null 的路径:
立即学习“Java免费学习笔记(深入)”;
示例代码:
public static void printClassLoader(Class<?> clazz) {
ClassLoader loader = clazz.getClassLoader();
int level = 0;
while (loader != null) {
System.out.println("Level " + level + ": " + loader);
loader = loader.getParent();
level++;
}
System.out.println("Level " + level + ": Bootstrap ClassLoader (null)");
}
- 调用
printClassLoader(MyClass.class)可看到 App → Platform(JDK9+)或 Ext(JDK8)→ null - 调用
printClassLoader(String.class)在 JDK 8 输出 “Level 0: null”;JDK 9+ 则输出 PlatformClassLoader 后接 null
管理类加载器的关键实践
实际开发中,类加载器管理重在避免冲突和正确委派:
- 自定义类加载器应继承
java.lang.ClassLoader,并重写findClass(),而非直接覆盖loadClass()—— 否则会破坏双亲委派 - 若需打破委派(如热部署、插件隔离),可在
findClass()中优先尝试本地加载,失败再调用super.findClass() - 通过系统属性可查各加载器默认路径:
System.getProperty("sun.boot.class.path")(Bootstrap)、"java.ext.dirs"(扩展)、"java.class.path"(应用类路径)


















