【JVM】堆、方法区存的分别是什么?
2025/12/28...大约 2 分钟
JVM的三大组件是类加载、垃圾回收、运行时数据区。其中运行时数据区主要是如下:
运行时数据区
├── 线程共享区域
│ ├── 堆(Heap) ← 存放对象实例
│ └── 方法区(Method Area) ← 存放类信息、常量、静态变量等
│
└── 线程私有区域(每个线程独立一份)
├── 程序计数器(PC Register)← 当前执行指令地址
├── Java虚拟机栈(JVM Stack)← 方法调用的栈帧
└── 本地方法栈(Native Method Stack)一、堆
堆是 JVM 管理的内存中最大的一块,也是垃圾回收器(GC)管理的主要区域。
1. 存储内容
堆的核心职责极其纯粹:几乎所有的对象实例和数组都在这里分配内存。
new出来的对象。- 数组(即使是基本数据类型的数组,如
int[],也是对象,存于堆中)。 - 字符串常量池
2. 内存结构(分代模型)
为了优化垃圾回收效率,现代垃圾收集器通常基于分代收集理论将堆划分为不同的区域:
堆内存结构
├── 年轻代 (Young Generation, 约占1/3)
│ ├── Eden区(伊甸园区,80%):新对象的出生地
│ ├── Survivor0区(幸存者区,10%)
│ └── Survivor1区(幸存者区,10%)
└── 老年代 (Old Generation, 约占2/3):长期存活对象的归宿二、方法区
1. 存储内容
方法区主要存储:
- 类信息:类的版本、字段、方法、接口、父类引用等。
- 运行时常量池:代码中直接写的字面量
- 数值:
100、3.14等 - 字符串引用:指向堆中字符串对象的引用
- 数值:
- 静态变量:存储的是:类级别的变量
- 基本类型:直接存储值的副本(
static int count = 100;→ 存储数值100) - 引用类型:存储指向堆中对象的引用(
static String name = "Tom";→ 存储引用) - 特殊优化:
static final编译时常量- 可能不在静态变量区实际存储
- 使用时直接从常量池取值
- 基本类型:直接存储值的副本(
- JIT 编译后的代码:即时编译器优化后的机器码。
- 方法字节码
- 符号引用
- 运行时常量池
- 常量池缓存
3. 方法区如何调用方法
- 加载与查找:JVM 根据方法引用,在方法区中找到该类的元数据(Method Info)。
- 栈帧创建:在Java 虚拟机栈中为当前线程创建一个新的栈帧(Stack Frame)。
- 数据装载:将方法的局部变量、参数信息等压入栈帧的局部变量表中。
- 执行指令:根据方法区中的字节码指令,CPU 执行具体逻辑(操作数栈进行计算)。
- 返回与清理:方法执行完毕,返回结果,当前栈帧出栈并被销毁。