5. JVM 的方法区
1. 什么是方法区
方法区是Java虚拟机(JVM)内存结构中的一个重要组成部分,主要用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
主要特点
共享内存区域:所有线程共享方法区
逻辑部分:是Java堆的逻辑组成部分
规范描述:在JVM规范中属于堆的一个逻辑部分,但习惯上被称为"非堆"(Non-Heap)
发展与演进
永久代(PermGen):在JDK7及之前,虚拟机用永久代来实现方法区。
元空间(Metaspace)(方法区):从JDK8开始,永久代被移除,改用本地内存实现的元空间(方法区)。
存储内容
方法区主要存储:
类信息(Class元数据)
运行时常量池
静态变量
即时编译器编译后的代码(JIT编译的本地代码)
方法代码
2. 元空间的常量池
常量池(Constant Pool)是 Java 类文件(.class 文件)和 JVM 运行时内存中的一个重要数据结构,用于存储类、方法、字段等相关的符号引用和字面量。
它分为两种:
Class 文件常量池(静态常量池,编译期生成)
运行时常量池(Runtime Constant Pool,JVM 运行时使用)
常量池 可以看作是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息 。
可以使用下面的指令查看字节码结构(类的基本信息、常量池、方法定义):
javap -vApplication.class
例如下图:
Class 文件常量池(静态常量池)
在 .class
文件中,常量池存储了类、方法、字段等的符号引用和字面量,主要包括:
字面量(Literals):
字符串(如
"Hello"
)整数、浮点数(如
100
,3.14
)布尔值(
true
/false
)null
符号引用(Symbolic References):
类和接口的全限定名(如
java/lang/Object
)字段的名称和描述符(如
name:Ljava/lang/String;
)方法的名称和描述符(如
main:([Ljava/lang/String;)V
)
特点:
编译期生成,存储在
.class
文件中不占用 JVM 内存,仅用于类加载时的解析
运行时常量池(Runtime Constant Pool)
当 JVM 加载类时,会将 Class 文件常量池的内容解析并存储到 方法区(元空间) 中的运行时常量池。它包含:
解析后的直接引用(如方法、字段的内存地址)
动态生成的常量(如
String.intern()
的字符串)JVM 运行时的符号引用解析结果
特点:
存储在 方法区(JDK 8 后是元空间)
可以动态添加(如
String.intern()
)如果内存不足,会抛出
OutOfMemoryError
3. 总结
3.1 什么是方法区?
- 方法区(Method Area)是各个线程共享的内存区域
- 主要存储类的信息、运行时常量池
- 虚拟机启动的时候创建,关闭虚拟机时释放
- 如果方法区域中的内存无法满足分配请求,则会抛出OutOfMemoryError:Metaspace
3.2 介绍一下运行时常量池
- 常量池:可以看作是一张表,虚拟机指令根据这张常量表找到要执行的类名方法名、参数类型、字面量等信息
- 当类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址
上一篇 下一篇