Skip to content

方法区(Method Area)

一、基础定义

  1. 线程共享:所有线程共享的内存区域,JVM启动时创建,虚拟机关闭时整体释放;
  2. 核心作用:存储所有已加载类的元数据、运行时常量池、静态常量、字节码;
  3. 溢出异常:内存耗尽抛出 java.lang.OutOfMemoryError: Metaspace

二、方法区存储内容

  1. 类元信息:类名、父类、接口、访问修饰符、字段、方法描述;
  2. ClassLoader类加载器信息;
  3. 运行时常量池:class文件常量池运行时加载到此,存放符号引用、字符串字面量、数字常量;
  4. 静态变量、编译后的字节码、注解信息。

三、Class常量池 & 运行时常量池

1. Class常量池

存于.class字节码文件内,一张符号信息表,保存未解析的符号引用:类名、方法名、字段名、字符串字面量。 查看命令:javap -v xxx.class,可打印完整常量池。 字节码指令中#数字就是查表索引,比如ldc #3读取常量池第3号字符串。

2. 运行时常量池

类加载时,把Class常量池加载进方法区,完成符号引用解析:将符号名转为内存真实地址,运行时直接寻址执行。

四、JDK7永久代 vs JDK8元空间(Metaspace)

JDK7:永久代 PermGen

  1. 位置:属于堆内存内部
  2. 缺陷:固定上限,大量动态生成类(ASM、反射、动态代理)极易发生永久代OOM。

JDK8:元空间 Metaspace

  1. 位置:移至操作系统本地堆外内存,不再占用Java堆;
  2. 参数配置:
    • -XX:MaxMetaspaceSize=8m 限制元空间最大容量,过小会触发Metaspace OOM;
  3. 优势:默认无硬性上限,受物理内存限制,大幅减少类加载溢出问题。

溢出演示

使用ASM动态循环生成大量Class,配合-XX:MaxMetaspaceSize=8m限制元空间,持续加载类后抛出Metaspace类型OOM。

五、面试简答

问:介绍方法区?

答:方法区是线程共享内存,JDK8实现为元空间,存放在本地堆外内存,JDK7及之前是堆内永久代。 主要存储类元信息、类加载器、运行时常量池。class文件自带常量池,类加载后载入运行时常量池,把符号引用解析为真实内存地址。 若元空间内存耗尽,抛出OutOfMemoryError: Metaspace,可通过-XX:MaxMetaspaceSize限制元空间最大容量。

Powered by VitePress 1.6.4 | 持续更新中