方法区存放类的元数据,包括类结构、常量、静态变量、JIT编译后的代码;HotSpot 1.8+用Metaspace替代永久代,使用本地内存并缓解GC压力。
方法区存放类的元数据,不是代码本身,也不是运行时创建的对象。
方法区存什么:类结构、常量、静态变量、JIT编译后的代码
它保存的是 Class 对象加载后生成的结构信息,比如字段名、方法签名、访问标志、注解、运行时常量池(注意:不是字符串常量池,后者在堆中)、static final 基本类型字面量。JVM 规范不强制要求实现方式,HotSpot 1.8+ 用 Metaspace 替代永久代,直接使用本地内存,避免 java.lang.OutOfMemoryError: PermGen space。
-
static变量值存在方法区,但引用的对象实例仍在堆中 -
String.intern()在 JDK 7+ 后,字符串常量池移到堆里,和方法区无关了 - JIT 编译后的本地代码(如 C1/C2 编译器产出)也缓存在方法区
为什么改用 Metaspace:解决永久代的硬限制和 GC 压力
永久代(PermGen)大小固定(如 -XX:MaxPermSize=256m),容易因动态类加载(如 OSGi、热部署、大量反射)撑爆。Metaspace 默认只受物理内存限制,且 GC 不扫描其内部结构——类卸载只发生在 Full GC 且满足条件时,由 ClassLoader 是否还存活决定。
- 可显式控制上限:
-XX:MaxMetaspaceSize=512m,不设则无上限 -
-XX:MetaspaceSize是触发首次 Metaspace GC 的阈值(类似初始堆大小) - 类卸载的前提是:该类所有实例已被回收 +
ClassLoader实例不可达 + 该类未被其他类引用
常见误判:String、static、Lambda 都不“全在”方法区
容易把“静态”“常量”“字节码”混为一谈。例如: