ClassLoader(类加载器)

ClassLoader(类加载器)

背景

  • JVM

定义

  • ClassLoader 是 JVM 提供的类加载机制(也是具体实现类的统称),核心作用是:将硬盘上的 .class 文件(字节码)加载到 JVM 内存中,并生成对应的 Class 对象,让程序能使用该类(比如 new 实例、调用静态方法)

ClassLoader 的核心作用

  • 加载:查找并读取 .class 文件到内存;
  • 链接:验证(校验字节码合法性)→ 准备(为静态变量分配内存)→ 解析(将符号引用转为直接引用);
  • 初始化:执行静态代码块、初始化静态变量(类的生命周期核心步骤);
  • 双亲委派(Parent Delegation Model):ClassLoader 最核心的设计原则

JVM 内置的 ClassLoader 分类(核心)

类加载器类型 作用 加载范围
启动类加载器(Bootstrap) 最顶层的类加载器,由 C/C++ 实现(无对应的 Java 类) JRE/lib/rt.jar(核心类,如 java.lang.*)
扩展类加载器(Extension) 继承自 Bootstrap,Java 实现 JRE/lib/ext/*.jar(扩展类)
应用程序类加载器(Application) 也叫系统类加载器,继承自 Extension,Java 实现 项目的 classpath 下的类(自己写的代码、第三方依赖)
  • 补充:自定义类加载器
    • 如果需要加载非 classpath 下的类(比如加载网络上的 .class 文件、加密的 .class 文件),可以继承 java.lang.ClassLoader 重写 findClass() 方法,实现自定义加载逻辑。

核心机制:双亲委派模型(Parent Delegation Model)(重点)

  • 定义:当一个类加载器收到类加载请求时,不会先自己加载,而是先把请求委托给父类加载器,直到传递到顶层的 Bootstrap 加载器;只有父类加载器无法加载该类(找不到对应的 .class 文件),子类加载器才会自己尝试加载。

  • 工作流程:

    1
    2
    3
    4
    5
    6
    graph TD
    A[应用程序类加载器] -->|委托加载| B[扩展类加载器]
    B -->|委托加载| C[启动类加载器]
    C -->|找不到 com.example.MyClass| B
    B -->|找不到 com.example.MyClass| A
    A -->|加载 classpath 下的 com/example/MyClass.class| D[生成 Class 对象]
  • 为什么要设计双亲委派?

    • 核心目的:保证类加载的安全性,避免核心类被篡改(比如自己写一个 java.lang.String 类,双亲委派会优先用 Bootstrap 加载核心库的 String,而非自定义的,防止恶意替换);
    • 避免类重复加载:同一个类只会被一个类加载器加载一次,保证内存中只有一份 Class 对象。

总结

  • ClassLoader 核心是将 .class 文件加载到 JVM 内存生成 Class 对象,JVM 内置 Bootstrap/Extension/Application 三层加载器;
  • 双亲委派模型是核心设计,优先委托父类加载器加载,保证核心类安全、避免类重复加载;
  • 类只有 “主动使用” 时才会加载,常见问题需区分 ClassNotFoundException(加载不到文件)和 NoClassDefFoundError(运行时缺失);
  • 自定义类加载器可实现热部署、插件化、加密加载等高级功能。