JVM的方法区和元空间(JDK7以前叫永久代)
方法区(Method Area)是 JVM 规范中定义的一个逻辑区域,用于存储被虚拟机加载的类信息、常量、静态变量等数据。虽然不同 JVM 实现对方法区的具体实现方式不同(如 HotSpot 在 Java 8 前使用永久代,Java 8 后使用元空间),但存储的核心内容基本一致。
方法区中存储的主要内容
- 类的结构信息
类型信息:类的全限定名、直接父类名、实现的接口列表、修饰符(public、abstract、final 等)。
字段信息:字段名称、类型、修饰符、字段的属性表(如常量值、注解等)。
方法信息:方法名称、返回类型、参数类型列表、修饰符、方法的字节码、异常表、局部变量表、操作数栈等。
类变量(静态变量):被static修饰的变量,关联到类而非实例。 - 运行时常量池(Runtime Constant Pool)
字面量:如文本字符串、final 常量值等。
符号引用:类和接口的全限定名、字段的名称和描述符、方法的名称和描述符。
翻译后的直接引用:类加载后,符号引用会被解析为直接引用(如内存地址)。 - 类加载器引用
指向加载该类的类加载器的引用。 - Class 对象
每个类被加载后,会在堆中生成一个对应的java.lang.Class对象,作为方法区中类数据的访问入口。 - JIT 编译后的代码缓存
即时编译器(JIT)编译后的本地机器码。 - 其他元数据
如方法表(Method Table),用于快速定位方法。
不同 JVM 版本的差异
Java 7 及以前(HotSpot):
运行时常量池、静态变量存储在永久代(PermGen)中。
Java 8 及以后(HotSpot):
永久代被元空间(Metaspace)替代,使用本地内存。
字符串常量池和静态变量移至堆内存,其他类元数据仍在元空间。
示例说明
假设存在一个类:
java
public class Example {
private static final String NAME = "example"; // 静态常量
private static int count = 0; // 静态变量
public void method() {
String str = "hello"; // 局部变量(存储在栈帧中)
// ...
}
}
NAME和count的定义信息存储在方法区。
"example"作为字符串常量存储在运行时常量池。
method()方法的字节码、局部变量表等信息存储在方法区。
总结
方法区是 JVM 存储类元数据的核心区域,确保类信息在运行时被高效访问。虽然具体实现(如永久代、元空间)会随 JVM 版本变化,但存储的核心内容保持不变。

浙公网安备 33010602011771号