JVM 垃圾回收算法详解(从基础到面试,一篇搞懂)
在 Java 中,我们不需要手动释放内存,但这并不意味着内存管理是"自动就简单"的。
JVM 通过一套复杂而高效的 垃圾回收(GC, Garbage Collection)算法 来管理内存。
本文将系统讲清:
- 常见 GC 算法
- 每种算法的原理与优缺点
- JVM 为什么采用"分代回收"
一、什么是垃圾回收?
👉 简单来说:
text
垃圾回收 = 找出"没用的对象"并释放内存
核心问题有两个:
text
1. 如何判断对象是否死亡?
2. 如何回收这些对象?
👉 第一问已经解决(可达性分析)
👉 本文重点:第二问(回收算法)
二、三大基础垃圾回收算法
1️⃣ 标记-清除算法(Mark-Sweep)
👉 原理:
text
第一步:标记所有"存活对象"
第二步:清除未标记对象(垃圾)
👉 图示理解:
text
[对象1][对象2][垃圾][对象3][垃圾]
↓ 标记
[✔][✔][ ][✔][ ]
↓ 清除
[对象1][对象2][ ][对象3][ ]
✅ 优点:
- 实现简单
- 不需要移动对象
❌ 缺点:
text
1. 内存碎片严重
2. 分配大对象困难
三、标记-复制算法(Copying)
👉 原理:
text
把内存分成两块(A / B)
使用 A:
复制存活对象到 B
清空 A
交换 A / B
👉 图示:
text
A区:[对象][垃圾][对象][垃圾]
↓ 复制
B区:[对象][对象]
↓ 清空
A区:空
✅ 优点:
text
无内存碎片
分配速度快
❌ 缺点:
text
内存利用率低(只能用一半)
四、标记-整理算法(Mark-Compact)
👉 原理:
text
标记存活对象
把所有存活对象"往一边挪"
清理边界外空间
👉 图示:
text
原始:[对象][垃圾][对象][垃圾][对象]
↓ 整理
[对象][对象][对象][ ][ ]
✅ 优点:
text
无内存碎片
空间利用率高
❌ 缺点:
text
移动对象成本高
五、为什么需要分代回收?
👉 这是 JVM 的核心优化思想!
📌 经验规律:
text
大部分对象"朝生夕死"
少数对象长期存活
👉 所以 JVM 把堆分为:
text
新生代(Young)
老年代(Old)
六、分代回收策略
1️⃣ 新生代(Young)
👉 特点:
text
对象多,但存活率低
👉 使用算法:
text
标记-复制算法
👉 原因:
- 垃圾多 → 复制成本低
- 追求速度
2️⃣ 老年代(Old)
👉 特点:
text
对象少,但存活率高
👉 使用算法:
text
标记-清除 或 标记-整理
👉 原因:
- 不适合复制(太多对象要复制)
- 更关注空间利用率
七、经典垃圾回收器(了解)
虽然算法是基础,但 JVM 实际用的是"回收器组合":
常见回收器:
- Serial(单线程)
- ParNew(多线程)
- CMS(并发标记清除)
- G1(分区回收)
👉 举例:
- CMS:基于标记-清除(低停顿)
- G1:结合复制 + 整理(现代主流)
八、面试高频总结
✔ 常见 GC 算法有哪些?
text
标记-清除
标记-复制
标记-整理
✔ 各自优缺点?
👉 一句话总结:
text
清除:简单但有碎片
复制:快但浪费空间
整理:无碎片但慢
✔ 为什么要分代?
text
不同对象生命周期不同 → 用不同算法更高效
✔ 新生代为什么用复制算法?
text
对象存活少 → 复制成本低
✔ 老年代为什么不用复制?
text
存活对象多 → 复制成本高
九、终极总结
text
GC 本质:
找到垃圾 → 用合适算法回收
再补一句更核心的:
text
分代 + 不同算法组合 = JVM 高性能的关键
十、结语
垃圾回收算法是 JVM 的核心:
- 理解它 → 才能理解 GC
- 理解 GC → 才能优化性能
- 优化性能 → 才能写高质量 Java 程序