主题
界面
主题
「JVM 把内存分成几块」是面试第一题,但背概念不如看真实日志。
★ 本节用 -Xlog:gc 采集了本项目自己程序的一手日志*:
Using G1 | Heap Region Size: 4M
Heap Min: 8M / Initial: 508M / Max: 8116M
GC(0) Pause Young (Normal) (G1 Evacuation Pause)
Eden regions: 12->0(58) Survivor: 0->1(2) Old: 1->1 Humongous: 0->0★ 线上 80% 的 JVM 故障只有三种 ✗:OOM(堆/元空间)、GC 停顿过长、栈溢出 —— 看懂内存结构与 GC 日志是处理它们的前提 ✓✓
| 区域 | 线程 | 放什么 | OOM/错误 |
|---|---|---|---|
| 堆 | 共享 ★★★ | 对象实例 | Java heap space ✗ |
| 虚拟机栈 | 私有 ★★ | 栈帧 | StackOverflowError ✗ |
| 本地方法栈 | 私有 | native 方法的栈帧 | StackOverflowError ✗ |
| 元空间 | 共享 ★★ | 类元数据 | Metaspace ✗ |
| 程序计数器 | 私有 | 字节码行号 | 唯一不会 OOM ✓ |
★ 一条对应:栈溢出查递归;堆 OOM 查大对象/泄漏;元空间 OOM 查动态类生成 ✓✓✓
G1 把堆切成 1~32M 的 Region(本机 4M)——Eden/Survivor/Old 不再物理连续,都是 Region 的逻辑角色 ✓✓✓
实测 GC(0):Eden 12 个 Region 清空(12→0),存活对象复制(Evacuate)进 Survivor(0→1)✓✓
| 区域 | 放什么 | 回收 |
|---|---|---|
| Eden ★★★ | 新对象 | Minor GC(频繁、快 ✓) |
| Survivor ★★ | Minor GC 存活者 | 晋升 Old 前的缓冲(年龄阈值 15) |
| Old ★★ | 长期存活对象 | Mixed/Full GC(慢 ✗) |
| Humongous ★★★ | ≥ Region 一半的大对象 | 直接 Old,碎片风险 ✗✗ |
★★★ Humongous 是 G1 经典事故源 ✗✗:本机 Region 4M → 对象 ≥ 2M 即 Humongous ✗ —— 读一个 10MB 文件 = 3 个 Humongous ✗✗ —— 大对象会触发 Full GC 甚至 OOM ✗✗✓ 对策:分块处理、调大 Region(-XX:G1HeapRegionSize)✓✓
类加载检查 → 分配内存(TLAB 上,无锁 ✓)→ 零初始化 → 设对象头 → 执行 <init>TLAB:每线程在 Eden 私有的一小块,分配只是指针移动,纳秒级 ✓✓✓ —— 「Java 创建对象很贵」这个印象过时了 ✓✓
Heap Min 8M / Initial 508M / Max 8116M ✓ —— 生产建议 Initial = Max(-Xms = -Xmx,避免运行时扩容抖动)✓✓✓; Region Size 随堆自动算(8G 堆 → 4M ✓)
java "-Xlog:gc*" -cp java-deep/target/classes cn.kb.learn.deep.jvm.GcLessonjava "-XX:G1HeapRegionSize=16m" ...byte[] all = Files.readAllBytes(Path.of("big.csv")); // ✗✗ 10MB = Humongous代码:labs/java-deep/src/main/java/cn/kb/learn/deep/jvm/GcLesson.java(100 轮 × 1MB 短命对象)
实测输出(关键部分):
[0.091s] Using G1
[0.103s] Heap Region Size: 4M
[0.104s] Heap Min Capacity: 8M | Initial Capacity: 508M | Max Capacity: 8116M
[0.206s] GC(0) Pause Young (Normal) (G1 Evacuation Pause)
[0.212s] GC(0) Eden regions: 12->0(58) | Survivor: 0->1(2) | Old: 1->1★ 100 轮 × 1MB 短命对象 = 一次 Young GC 完成 ✓ —— 这就是「分代假说:绝大多数对象朝生夕死」的直接证据 ✓✓✓
| # | 错误 | 说明 |
|---|---|---|
| 1 | 以为创建对象很贵 ✗ | TLAB 纳秒级 ✓✓ |
| 2 | 一次性读大文件 ✗✗ | Humongous ✗✗ |
| 3 | -Xms ≠ -Xmx ✗ | 扩容抖动 ✓ |
| 4 | 元空间 OOM 去查堆 ✗✗ | 查动态类生成 ✓ |
| 5 | StackOverflow 查堆 ✗✗ | 查递归与栈深 ✓✓ |
验收方式:能对着一份 GC 日志说出各代行为与是否健康。
扩展任务:制造一次元空间 OOM(CGlib 生成大量类),记录日志并写分析 ✓✓