运行时数据区
程序计数器(PC Register)
程序计数器是一块较小的内存空间,用于存储当前线程正在执行的字节码指令地址。特点
- 线程私有:每个线程都有自己的程序计数器
- 唯一不会 OOM:不会发生 OutOfMemoryError
- 执行 Native 方法时为空:此时计数器值为 undefined
作用
虚拟机栈(VM Stack)
虚拟机栈是 Java 方法执行的内存模型,每个方法执行时都会创建一个栈帧。栈帧结构
局部变量表
存储方法参数和局部变量,以 Slot 为单位。| 数据类型 | Slot 数量 |
|---|---|
| boolean, byte, char, short, int, float | 1 |
| long, double | 2 |
| reference | 1 |
操作数栈
用于计算过程中的临时存储。栈溢出
相关参数
本地方法栈(Native Method Stack)
与虚拟机栈类似,但用于执行 Native 方法(C/C++ 实现)。堆(Heap)
堆是 JVM 管理的最大内存区域,用于存放对象实例。堆内存结构(JDK 8)
对象分配过程
堆内存参数
OutOfMemoryError
方法区(Method Area)
方法区用于存储类信息、常量、静态变量、即时编译器编译后的代码等。JDK 版本变化
| 版本 | 实现 | 存储位置 |
|---|---|---|
| JDK 7 及之前 | 永久代(PermGen) | 堆内存 |
| JDK 8 及之后 | 元空间(Metaspace) | 本地内存 |
方法区内容
运行时常量池
元空间参数
元空间溢出
直接内存(Direct Memory)
直接内存不属于 JVM 运行时数据区,但也被频繁使用。特点
- 不受 JVM 堆大小限制
- 减少数据拷贝,IO 性能更好
- 分配和回收成本较高
使用场景
参数配置
内存区域总结
| 区域 | 线程 | 作用 | 异常 |
|---|---|---|---|
| 程序计数器 | 私有 | 记录执行位置 | 无 |
| 虚拟机栈 | 私有 | 方法执行 | StackOverflowError, OOM |
| 本地方法栈 | 私有 | Native 方法执行 | StackOverflowError, OOM |
| 堆 | 共享 | 对象实例 | OutOfMemoryError |
| 方法区 | 共享 | 类信息、常量 | OutOfMemoryError |
小结
- 程序计数器:线程私有,记录执行位置,唯一不会 OOM
- 虚拟机栈:线程私有,方法执行的栈帧
- 堆:线程共享,对象实例存储,GC 主要区域
- 方法区:线程共享,类信息和常量池,JDK 8 后为元空间
- 理解内存结构是理解 GC 和调优的基础