应用程序类加载器(也称系统类加载器)负责加载classpath路径下的用户类和第三方jar,是扩展类加载器的子加载器,遵循双亲委派模型,确保核心类不被污染;可通过classloader.getsystemclassloader()获取,日常开发中绝大多数类由它加载。

应用程序类加载器(Application ClassLoader),也叫系统类加载器(System ClassLoader),是 Java 类加载体系中与开发者关系最直接的一层。它负责加载用户编写的类,也就是放在 classpath(包括 -cp 指定路径、IDE 的 output 目录、Maven 的 target/classes 等)下的所有 .class 文件和 JAR 包中的类。
它从哪儿加载类?
它默认读取以下位置的类:
- JVM 启动时通过 -cp 或 -classpath 参数指定的路径
- 环境变量 CLASSPATH 所配置的路径(若未显式指定 -cp,则使用该值)
- IDE(如 IntelliJ 或 Eclipse)自动配置的编译输出目录(如 out/production 或 target/classes)
- Maven/Gradle 构建产物中的依赖 JAR(通过其内部 ClassLoader 委托机制间接参与)
它在类加载器层级中处于什么位置?
它是扩展类加载器(Extension ClassLoader)的子加载器,而扩展类加载器又是启动类加载器(Bootstrap)的子加载器。整个链条是:
Bootstrap → Extension → Application
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
它不是由 Java 代码实现的(Bootstrap 是 C++ 实现,Extension 和 Application 是 Java 实现),但你可以通过 ClassLoader.getSystemClassLoader() 获取它的实例。注意:它不是当前线程上下文类加载器(Context ClassLoader)的默认值——JVM 启动后,主线程的上下文类加载器默认就是它本身。
它怎么工作?遵循双亲委派吗?
是的,它严格遵循双亲委派模型:
- 当它收到一个类加载请求(比如 Class.forName("com.example.Service")),不会立刻查找自己的 classpath,而是先委托给父加载器(Extension)去尝试加载
- Extension 又会委托给 Bootstrap;如果 Bootstrap 找不到(比如非 java.* 包),就逐级退回
- 最终由 Application 加载器在 classpath 中定位并加载该类
这种设计保证了像 java.lang.String 这样的核心类永远由 Bootstrap 加载,避免被用户自定义的同名类“污染”或替换。
它和我们写代码有什么关系?
绝大多数日常开发中,你写的类、引用的第三方库(非 JDK 内置)、Spring Boot 的 starter 依赖等,都是由它加载的。这意味着:
- 如果你把某个类打进了 JAR,但没放进 classpath,NoClassDefFoundError 就很可能来自它找不到该类
- 用 Thread.currentThread().getContextClassLoader() 获取的,通常就是它——很多框架(如 JDBC、JAX-WS)依赖这个加载器去加载用户提供的 SPI 实现类
- 自定义类加载器一般以它为父加载器(而非 null),这样才能访问到你的业务类和标准库
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










