应用程序类加载器负责加载classpath路径下的.class文件或JAR包中的类,按全限定名查找,依赖启动时指定的classpath,自动参与双亲委派,可手动获取但不触发初始化。

Java 中的应用程序类加载器(Application ClassLoader,也叫系统类加载器)负责加载用户编写的类,即放在 classpath 路径下的类文件(如 .class 文件或 JAR 包中的类)。它不直接解析源码,而是根据类的全限定名(如 com.example.MyApp),将对应的字节码加载进 JVM。
它从哪找类?——classpath 是关键
Application ClassLoader 依赖 JVM 启动时指定的 classpath(可通过 -cp 或 -classpath 参数设置,未显式指定则默认为当前目录 .)。它会按顺序扫描这些路径:
- 当前目录(
.)下的.class文件(例如MyApp.class) - 子目录结构匹配包名(如
com/example/MyApp.class对应com.example.MyApp) - JAR 或 ZIP 文件(如
lib/myapp.jar),并检查其内部的目录结构和META-INF/MANIFEST.MF(如有Class-Path属性,也会递归加入)
它怎么触发加载?——通常不手动调用
绝大多数情况下,你不需要显式使用 Application ClassLoader。JVM 在以下时机自动委托它加载:
- 执行
java MyApp时,JVM 用它加载MyApp的主类 - 运行中首次遇到某个类(如调用
new SomeService()),且该类尚未被加载时,JVM 按双亲委派模型向上委托;若 Bootstrap 和 Extension 加载器都找不到,就由 Application ClassLoader 尝试加载 - 通过
Class.forName("com.example.User")(无参数重载)时,默认使用当前线程上下文类加载器(Thread Context ClassLoader),而主线程默认就是 Application ClassLoader
能手动用它吗?——可以,但要小心路径和可见性
你可以显式获取并使用它,例如:
立即学习“Java免费学习笔记(深入)”;
ClassLoader appCl = ClassLoader.getSystemClassLoader();
Class<?> clazz = appCl.loadClass("com.example.MyTask"); // 注意:不会初始化类
Object instance = clazz.getDeclaredConstructor().newInstance();
注意几点:
-
loadClass()只加载、链接,不触发初始化(即不执行 static 块);需要初始化请用Class.forName(String) - 如果类不在 classpath 中,会抛
ClassNotFoundException - 它无法加载位于模块路径(
--module-path)中的模块类(那是 ModuleLayer 管理的范畴) - 不能加载被父加载器(如 Bootstrap)已加载的类(比如
java.lang.String),这是双亲委派的保护机制
常见误区提醒
别混淆几个概念:
- Application ClassLoader ≠ 自定义 ClassLoader:后者需继承
ClassLoader并重写findClass() - classpath 不等于项目根目录:IDE(如 IntelliJ)可能把
out/production或target/classes设为 classpath,而非你写的src目录 - 它不解析
.java源文件:编译必须先用javac生成.class,否则加载失败


















