核心定义与地位规范定义方法区与Java堆一样是各个线程共享的内存区域。别名虽然JVM规范把它描述为堆的一个逻辑部分但它有一个别名叫做非堆目的就是为了和Java堆区分开来。作用如果说堆是存储对象的区域那么方法区就是存储类模版的区域。存储内容当 JVM 加载 .class 文件时会将解析后的数据存储在方法区中。类型信息对每个加载的类型类 class、接口 interface、枚举 enum、注解 annotation方法区存储类型的全限定名Full Qualified Name。直接超类的全限定名接口和 java.lang.Object 除外。类型的修饰符public, abstract, final。直接接口列表。字段/域信息存储类中声明的所有字段字段名称、类型、修饰符public, private, volatile, transient 等。字段在类中的声明顺序。方法信息存储类中所有方法的数据方法名称、返回类型、参数列表数量及类型按顺序。方法修饰符。非抽象方法的字节码Bytecode、操作数栈深度、局部变量表大小。异常表记录每个异常处理代码段的开始/结束位置、处理代码的偏移量以及捕获的异常类型。静态变量JDK 6 及以前静态变量存储在方法区永久代中。JDK 7 及以后静态变量Static Fields随类对象java.lang.Class 实例一起转移到了 Java 堆中。注方法区仅保留类的元数据实际的静态变量数据位于堆中。JIT 代码缓存即时编译器JIT编译后的热点方法机器码也存储在方法区中部分实现将其划分为独立区域。运行时常量池这是方法区中最重要的子区域之一。来源由 .class 文件中的常量池表加载而来。内容包含编译期生成的各种字面量字符串、基本类型常量和符号引用类、字段、方法的符号描述。解析Resolution在类加载的解析阶段JVM会将常量池内的符号引用替换为直接引用真实的内存地址或偏移量。动态性相对于 .class 文件常量池运行时常量池可以在运行期动态添加常量如 String.intern()。演变历史从永久代到元空间HotSpot 虚拟机对方法区的实现经历了从 JVM 内部管理到本地内存管理的转变。阶段实现方式存储位置关键变化JDK6及以前永久代JVM虚拟机内存受 -XX:MaxPermSize 限制易发生 OOMJDK 7永久代JVM虚拟机内存符号引用、静态变量、字符串常量池搬移至 Java 堆JDK8及以后元空间本地内存彻底废除永久代元空间改用本地内存减少 OOM风险内部优化结构虚方法表为了提高多态调用的执行效率JVM 在方法区为每个类维护了高效的数据结构虚方法表vtable存储虚方法的直接引用。接口方法表itable存储接口方法的实现映射。作用在动态绑定时无需向上遍历继承树直接通过索引即可定位方法入口。内存管理与类卸载方法区的垃圾回收GC频率极低主要关注废弃常量和无用的类。类卸载Class Unloading的三个必要条件该类所有的实例已被回收堆中无实例。加载该类的类加载器ClassLoader已被回收。该类的 java.lang.Class 对象没有任何引用无法通过反射访问。场景在频繁使用反射、动态代理、CGLib以及热部署的场景中类卸载能力至关重要否则会导致元空间持续膨胀。异常与调优参数相关异常OutOfMemoryError: Metaspace元空间耗尽。通常是因为加载类过多或类加载器泄露导致类无法卸载。关键参数JDK 8-XX:MetaspaceSize初始水位线。达到此值会触发 Full GC并动态调整该值。建议设置为与最大值一致以避免启动时频繁 GC。-XX:MaxMetaspaceSize限制元空间最大可用内存防止其无限占用系统物理内存。默认值为 -1不限制。-XX:MinMetaspaceFreeRatio / -XX:MaxMetaspaceFreeRatio控制 GC 后元空间空闲比例的上下限。总结Q1JDK 8 以后静态变量存在哪里A存在 Java 堆中。静态变量随类对象Class 实例存储而类对象在 JDK 7 起就已搬移至堆。Q2元空间Metaspace会发生 OOM 吗A会。虽然它使用本地内存但如果物理内存耗尽或者通过 -XX:MaxMetaspaceSize设置了上限并触顶依然会抛出 OutOfMemoryError: Metaspace。Q3为什么建议将 -XX:MetaspaceSize 设置得大一些A该参数是触发 GC 的阈值。如果设置过小JVM 启动初期加载大量类时会频繁触发 Full GC来动态调整水位线导致应用响应变慢。建议设置为与最大值相等。Q4方法区和永久代是什么关系A方法区是 JVM 规范中的定义永久代PermGen是 HotSpot 虚拟机在 JDK 7及以前对该规范的具体实现。Q5哪些操作会导致方法区内存溢出A大量使用动态代理JDK Proxy/CGLib、热部署框架OSGi、频繁自定义 ClassLoader以及加载过多的第三方库如 Spring 等框架生成的动态类。
5.JVM-方法区
发布时间:2026/6/6 18:40:57
核心定义与地位规范定义方法区与Java堆一样是各个线程共享的内存区域。别名虽然JVM规范把它描述为堆的一个逻辑部分但它有一个别名叫做非堆目的就是为了和Java堆区分开来。作用如果说堆是存储对象的区域那么方法区就是存储类模版的区域。存储内容当 JVM 加载 .class 文件时会将解析后的数据存储在方法区中。类型信息对每个加载的类型类 class、接口 interface、枚举 enum、注解 annotation方法区存储类型的全限定名Full Qualified Name。直接超类的全限定名接口和 java.lang.Object 除外。类型的修饰符public, abstract, final。直接接口列表。字段/域信息存储类中声明的所有字段字段名称、类型、修饰符public, private, volatile, transient 等。字段在类中的声明顺序。方法信息存储类中所有方法的数据方法名称、返回类型、参数列表数量及类型按顺序。方法修饰符。非抽象方法的字节码Bytecode、操作数栈深度、局部变量表大小。异常表记录每个异常处理代码段的开始/结束位置、处理代码的偏移量以及捕获的异常类型。静态变量JDK 6 及以前静态变量存储在方法区永久代中。JDK 7 及以后静态变量Static Fields随类对象java.lang.Class 实例一起转移到了 Java 堆中。注方法区仅保留类的元数据实际的静态变量数据位于堆中。JIT 代码缓存即时编译器JIT编译后的热点方法机器码也存储在方法区中部分实现将其划分为独立区域。运行时常量池这是方法区中最重要的子区域之一。来源由 .class 文件中的常量池表加载而来。内容包含编译期生成的各种字面量字符串、基本类型常量和符号引用类、字段、方法的符号描述。解析Resolution在类加载的解析阶段JVM会将常量池内的符号引用替换为直接引用真实的内存地址或偏移量。动态性相对于 .class 文件常量池运行时常量池可以在运行期动态添加常量如 String.intern()。演变历史从永久代到元空间HotSpot 虚拟机对方法区的实现经历了从 JVM 内部管理到本地内存管理的转变。阶段实现方式存储位置关键变化JDK6及以前永久代JVM虚拟机内存受 -XX:MaxPermSize 限制易发生 OOMJDK 7永久代JVM虚拟机内存符号引用、静态变量、字符串常量池搬移至 Java 堆JDK8及以后元空间本地内存彻底废除永久代元空间改用本地内存减少 OOM风险内部优化结构虚方法表为了提高多态调用的执行效率JVM 在方法区为每个类维护了高效的数据结构虚方法表vtable存储虚方法的直接引用。接口方法表itable存储接口方法的实现映射。作用在动态绑定时无需向上遍历继承树直接通过索引即可定位方法入口。内存管理与类卸载方法区的垃圾回收GC频率极低主要关注废弃常量和无用的类。类卸载Class Unloading的三个必要条件该类所有的实例已被回收堆中无实例。加载该类的类加载器ClassLoader已被回收。该类的 java.lang.Class 对象没有任何引用无法通过反射访问。场景在频繁使用反射、动态代理、CGLib以及热部署的场景中类卸载能力至关重要否则会导致元空间持续膨胀。异常与调优参数相关异常OutOfMemoryError: Metaspace元空间耗尽。通常是因为加载类过多或类加载器泄露导致类无法卸载。关键参数JDK 8-XX:MetaspaceSize初始水位线。达到此值会触发 Full GC并动态调整该值。建议设置为与最大值一致以避免启动时频繁 GC。-XX:MaxMetaspaceSize限制元空间最大可用内存防止其无限占用系统物理内存。默认值为 -1不限制。-XX:MinMetaspaceFreeRatio / -XX:MaxMetaspaceFreeRatio控制 GC 后元空间空闲比例的上下限。总结Q1JDK 8 以后静态变量存在哪里A存在 Java 堆中。静态变量随类对象Class 实例存储而类对象在 JDK 7 起就已搬移至堆。Q2元空间Metaspace会发生 OOM 吗A会。虽然它使用本地内存但如果物理内存耗尽或者通过 -XX:MaxMetaspaceSize设置了上限并触顶依然会抛出 OutOfMemoryError: Metaspace。Q3为什么建议将 -XX:MetaspaceSize 设置得大一些A该参数是触发 GC 的阈值。如果设置过小JVM 启动初期加载大量类时会频繁触发 Full GC来动态调整水位线导致应用响应变慢。建议设置为与最大值相等。Q4方法区和永久代是什么关系A方法区是 JVM 规范中的定义永久代PermGen是 HotSpot 虚拟机在 JDK 7及以前对该规范的具体实现。Q5哪些操作会导致方法区内存溢出A大量使用动态代理JDK Proxy/CGLib、热部署框架OSGi、频繁自定义 ClassLoader以及加载过多的第三方库如 Spring 等框架生成的动态类。