JVM的方法区和元空间(JDK7以前叫永久代)

方法区(Method Area)是 JVM 规范中定义的一个逻辑区域,用于存储被虚拟机加载的类信息、常量、静态变量等数据。虽然不同 JVM 实现对方法区的具体实现方式不同(如 HotSpot 在 Java 8 前使用永久代,Java 8 后使用元空间),但存储的核心内容基本一致。
方法区中存储的主要内容

  1. 类的结构信息
    类型信息:类的全限定名、直接父类名、实现的接口列表、修饰符(public、abstract、final 等)。
    字段信息:字段名称、类型、修饰符、字段的属性表(如常量值、注解等)。
    方法信息:方法名称、返回类型、参数类型列表、修饰符、方法的字节码、异常表、局部变量表、操作数栈等。
    类变量(静态变量):被static修饰的变量,关联到类而非实例。
  2. 运行时常量池(Runtime Constant Pool)
    字面量:如文本字符串、final 常量值等。
    符号引用:类和接口的全限定名、字段的名称和描述符、方法的名称和描述符。
    翻译后的直接引用:类加载后,符号引用会被解析为直接引用(如内存地址)。
  3. 类加载器引用
    指向加载该类的类加载器的引用。
  4. Class 对象
    每个类被加载后,会在堆中生成一个对应的java.lang.Class对象,作为方法区中类数据的访问入口。
  5. JIT 编译后的代码缓存
    即时编译器(JIT)编译后的本地机器码。
  6. 其他元数据
    如方法表(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 版本变化,但存储的核心内容保持不变。

posted @ 2025-06-10 16:09  认真的刻刀  阅读(110)  评论(0)    收藏  举报