Java 类加载是 Java 虚拟机(JVM)在运行时动态加载 .class
文件到内存的过程。这个过程和类的生命周期紧密相关。我们来系统地学习下 Java 类加载的 过程、生命周期阶段、类加载器的作用 以及 相关细节和面试点。
Java 类从 .class
文件变成 JVM 可执行的对象代码,会经过 七个步骤,可以分为三大阶段:
加载(Loading)
↓
验证(Verification)
↓
准备(Preparation)
↓
解析(Resolution)
↓
初始化(Initialization)
↓
使用(Using)
↓
卸载(Unloading)
.class
文件并读取其字节流。java.lang.Class
类的实例。static int a = 5;
// 在这阶段,a 分配了内存,值为 0,不是 5
"java/lang/Object"
转成真实的类对象。()
方法(静态代码块和静态变量初始化)。ClassLoader
被 GC 回收,并且该类无任何实例。Java 使用双亲委派模型:
BootstrapClassLoader(引导类加载器)
↑
ExtClassLoader(扩展类加载器)
↑
AppClassLoader(应用类加载器)
↑
自定义ClassLoader(如 SPI、插件等)
java.lang.String
也不会被加载)。点 | 内容 |
---|---|
类何时初始化? | 有静态变量/静态代码块时且被访问 |
类何时不会初始化? | 引用数组不会触发类初始化 |
和构造器区别? |
是类初始化,构造器是对象初始化 |
自定义 ClassLoader 作用? | 动态加载模块、热更新、插件系统 |
双亲委派有什么好处? | 安全、避免重复加载 |
class A {
static {
System.out.println("A static block");
}
}
public class Test {
public static void main(String[] args) {
A[] arr = new A[10]; // 会不会输出 A static block?
}
}
✅ 不会,因为只是创建了数组,没有初始化类 A
。
如果你想我配张图解释类加载的阶段,或者深入讲讲某个阶段的底层原理(比如常量池解析),我也可以继续展开。要不要?