classloader将类信息加载到方法区是贯穿“加载→连接→初始化”全过程的系统性行为:加载阶段完成主体结构并创建class对象;连接阶段包含验证、准备(分配内存设默认值)、解析(符号引用转直接引用);初始化阶段执行static代码块和赋值语句,写入程序员定义的初始值。

ClassLoader 将类信息加载到方法区,不是一步到位的操作,而是贯穿“加载→连接→初始化”全过程的系统性行为。真正把类的结构数据落进方法区(JDK 8+ 是元空间)是在加载阶段完成主体结构,后续连接阶段持续填充和校验,最终由初始化阶段触发实际值写入。
加载阶段:把字节码变成方法区里的运行时结构
这是整个流程的起点,也是类信息首次进入方法区的关键环节:
- ClassLoader 根据类的全限定名(如 java.util.ArrayList),从文件系统、JAR 包、网络或动态生成等任意来源获取二进制字节流;
- JVM 将该字节流解析为符合规范的类结构,包括常量池、字段表、方法表、接口信息、属性等,并把这些数据组织成方法区(元空间)中的运行时数据结构;
- 同时在堆中创建一个 java.lang.Class 对象,它内部持有指向方法区中该类数据结构的引用,成为 Java 层访问类元数据的统一入口。
验证与准备阶段:在方法区中加固和分配基础内存
验证阶段不改变方法区结构,但确保已加载的数据合法可信;准备阶段则正式为静态变量在方法区分配内存:
- 验证(Verification)会检查字节码格式、语义逻辑、指令安全性和符号引用存在性,所有校验失败都会抛出异常(如 ClassFormatError、NoSuchMethodError),阻止非法类污染方法区;
- 准备(Preparation)为类的 static 变量(非 final static 常量)在方法区分配内存,并设为默认值(如 int → 0,reference → null);final static 字段因编译期已确定,其值直接进入常量池,不在此阶段赋值。
解析阶段:把符号引用转成方法区内的真实地址
解析是连接阶段的第三步,它让方法区中的类真正“活”起来,能互相定位和调用:
- 将常量池中对类、字段、方法等的符号引用(比如字符串 "java/lang/Object.toString()Ljava/lang/String;")替换为指向方法区中对应实体的直接引用(如内存偏移量、指针或句柄);
- 这个过程可能延迟到初始化之后(尤其涉及接口方法或动态绑定时),但一旦完成,JVM 就能通过这些直接引用快速跳转,无需再查常量池。
初始化阶段:向方法区写入程序员定义的初始值
这是类加载流程的最后一步,也是唯一执行 Java 代码的阶段,直接影响方法区中静态变量的实际内容:
- 执行类的 static {} 静态代码块 和 static 字段的显式赋值语句(如 static int x = 10;);
- 这些操作的结果会更新方法区中对应静态变量的内存值——也就是说,方法区里存的不再是默认值,而是你写的初始值;
- 若类有父类,且父类尚未初始化,则先触发父类初始化,保证继承链上的静态内容按顺序就位。











