【Java-JVM】常用的垃圾回收算法有哪些?
·

Java常用垃圾回收算法详解
在 Java 虚拟机(JVM)中,垃圾回收(Garbage Collection, GC)负责自动管理内存,回收不再使用的对象。以下是常用的垃圾回收算法,我会用故事举例通俗解释:
1. 标记-清除算法(Mark-Sweep)
- 原理:
- 标记:遍历所有对象,标记哪些是存活对象(被引用的)。
- 清除:回收所有未标记的对象(垃圾)。
- 故事比喻:
想象一个仓库管理员(GC)需要清理仓库。他先给所有有用的货物贴上标签(标记),再把所有没标签的货物扔掉(清除)。 - 优缺点:
- ✅ 简单直接,不需要移动对象。
- ❌ 产生内存碎片(就像仓库里留下很多零散空位),可能影响大对象分配。
2. 复制算法(Copying)
- 原理:
- 将内存分为两半(From 区和 To 区)。
- 将 From 区的存活对象复制到 To 区。
- 清空整个 From 区。
- 故事比喻:
仓库有两间房(A 和 B),管理员先把 A 间有用的货物搬到 B 间,然后一键清空 A 间。 - 优缺点:
- ✅ 无内存碎片,回收高效。
- ❌ 浪费一半内存空间(永远有一间房空着)。
- 应用场景:年轻代(Young Generation)的 Survivor 区(如 Eden + S0/S1)。
3. 标记-整理算法(Mark-Compact)
- 原理:
- 标记:标记存活对象。
- 整理:将所有存活对象向内存一端移动。
- 清理:回收边界外的空间。
- 故事比喻:
管理员把仓库中有用的货物全部推到一侧码放整齐,然后把另一侧的空地一次性清理干净。 - 优缺点:
- ✅ 无内存碎片,空间利用率高。
- ❌ 移动对象成本高("整理"阶段耗时更长)。
- 应用场景:老年代(Old Generation),如 CMS 或 G1 的某些阶段。
4. 分代收集算法(Generational Collection)
- 原理:
- 分代:将堆内存分为年轻代(Young)和老年代(Old)。
- 回收策略:
- 年轻代:存活率低 → 用复制算法(快速回收)。
- 老年代:存活率高 → 用标记-清除或标记-整理(减少移动开销)。
- 故事比喻:
仓库分为新品区(年轻代)和古董区(老年代)。新品区经常大扫除(复制算法),古董区偶尔整理(标记-整理)。 - 优缺点:
- ✅ 针对性优化,平衡效率与空间。
- ❌ 实现复杂(需维护分代逻辑)。
- 应用场景:现代 JVM(如 HotSpot)的默认策略。
5. 分区算法(Region-Based)
- 原理:
将堆划分为多个小区域(Regions),独立回收。 - 代表:G1 垃圾回收器。
- 故事比喻:
把仓库分成多个小隔间,管理员每次只清理最乱的几个隔间,避免全仓停工。 - 优点:
- ✅ 可控停顿时间(避免全局 STW)。
- ✅ 灵活处理不同区域。
总结
| 算法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 标记-清除 | 老年代(CMS) | 简单 | 内存碎片 |
| 复制算法 | 年轻代(Survivor) | 无碎片、高效 | 浪费 50% 空间 |
| 标记-整理 | 老年代(Serial GC) | 无碎片、空间利用率高 | 移动对象成本高 |
| 分代收集 | 现代 JVM 堆 | 平衡效率与空间 | 实现复杂 |
| 分区算法(G1) | 大堆内存 | 可控停顿、灵活回收 | 内存占用稍高 |
核心思想:没有完美的算法,只有适合场景的策略。JVM 根据对象生命周期特点选择最优组合!
更多推荐



所有评论(0)