主题切换
方法区(Method Area)
一、基础定义
- 线程共享:所有线程共享的内存区域,JVM启动时创建,虚拟机关闭时整体释放;
- 核心作用:存储所有已加载类的元数据、运行时常量池、静态常量、字节码;
- 溢出异常:内存耗尽抛出
java.lang.OutOfMemoryError: Metaspace。
二、方法区存储内容
- 类元信息:类名、父类、接口、访问修饰符、字段、方法描述;
- ClassLoader类加载器信息;
- 运行时常量池:class文件常量池运行时加载到此,存放符号引用、字符串字面量、数字常量;
- 静态变量、编译后的字节码、注解信息。
三、Class常量池 & 运行时常量池
1. Class常量池
存于.class字节码文件内,一张符号信息表,保存未解析的符号引用:类名、方法名、字段名、字符串字面量。 查看命令:javap -v xxx.class,可打印完整常量池。 字节码指令中#数字就是查表索引,比如ldc #3读取常量池第3号字符串。
2. 运行时常量池
类加载时,把Class常量池加载进方法区,完成符号引用解析:将符号名转为内存真实地址,运行时直接寻址执行。
四、JDK7永久代 vs JDK8元空间(Metaspace)
JDK7:永久代 PermGen
- 位置:属于堆内存内部;
- 缺陷:固定上限,大量动态生成类(ASM、反射、动态代理)极易发生永久代OOM。
JDK8:元空间 Metaspace
- 位置:移至操作系统本地堆外内存,不再占用Java堆;
- 参数配置:
-XX:MaxMetaspaceSize=8m限制元空间最大容量,过小会触发Metaspace OOM;
- 优势:默认无硬性上限,受物理内存限制,大幅减少类加载溢出问题。
溢出演示
使用ASM动态循环生成大量Class,配合-XX:MaxMetaspaceSize=8m限制元空间,持续加载类后抛出Metaspace类型OOM。
五、面试简答
问:介绍方法区?
答:方法区是线程共享内存,JDK8实现为元空间,存放在本地堆外内存,JDK7及之前是堆内永久代。 主要存储类元信息、类加载器、运行时常量池。class文件自带常量池,类加载后载入运行时常量池,把符号引用解析为真实内存地址。 若元空间内存耗尽,抛出OutOfMemoryError: Metaspace,可通过-XX:MaxMetaspaceSize限制元空间最大容量。