REJAVA / LEARNING NOTES
第9课速查:JVM(Java 虚拟机)内存区域
随时回查术语、规则和示例;完整解释见对应课程。
根据课程材料整理
本次更新说明
- 整理为公开学习笔记,保留要点、对照表与练习入口。
1 · 五块区域
| 区域 | 谁的 | 错误 |
|---|---|---|
| 程序计数器 | 线程私有 | 规范未列 |
| 虚拟机栈 | 线程私有 | SOE、OOM |
| 本地方法栈 | 线程私有 | SOE、OOM |
| 堆 | 共享 | OOM |
| 方法区 | 共享 | OOM |
和“执行”有关的私有,和“数据”有关的共享。直接内存不属于这五块,也会 OOM。
2 · 栈
每调用一个方法压一个栈帧:局部变量表、操作数栈、运行时常量池引用。
太深 → StackOverflowError(栈溢出错误);-Xss 设大小(Linux/x64 默认 1024 KB)。新建线程分不出栈 → OOM。
局部变量私有,它引用的对象仍在堆上。
3 · 堆
所有对象和数组,GC(垃圾回收) 自动回收。-Xms 初始、-Xmx 最大,服务器常设相同。
满了 → OutOfMemoryError: Java heap space。常见:一次查太多、集合只加不删 → 分页分批。
4 · 方法区与元空间
| JDK 6 | JDK 7 | JDK 8+ | |
|---|---|---|---|
| 类元数据 | 永久代 | 永久代 | 元空间 |
| 字符串常量池 | 永久代 | 堆 | 堆 |
| 静态变量 | 永久代 | — | 堆 |
方法区=规范;永久代/元空间=HotSpot 实现。换的原因:MaxPermSize 定死难调;合并 JRockit(JEP 122)。
MaxMetaspaceSize 默认不限 → 建议设上限;超了 → OOM: Metaspace。JDK 17/21 写 MaxPermSize 直接启动失败。
5 · new 一个对象
类加载检查 → 分配内存(指针碰撞/空闲列表;TLAB(线程本地分配缓冲),不够再 CAS(比较并交换))→ 零值 → 对象头 → <init>。
字节码:new → dup → invokespecial <init>。new 完还没创建完。
对象=对象头(Mark Word(标记字段)+类型指针)+实例数据+对齐填充。示例环境 HotSpot 17/21 默认配置:头 12 字节,new Object() 16 字节(实现值,不是规范规定)。HotSpot 用直接指针访问。
6 · 看报错判断区域
StackOverflowError(栈溢出错误) → 栈:递归无出口/数据成环。
OOM: Java heap space → 堆:对象堆积。
OOM: Metaspace → 元空间:动态生成类、加载器不释放。
OOM: GC overhead limit exceeded → 按堆处理。
先判断区域,再抓现场;不要先调大参数。