JVM 垃圾回收(GC)算法的核心目标是精准识别堆中无用对象并回收其内存,同时兼顾回收效率、内存利用率和停顿时间。算法的演变围绕「标记 - 清理 - 整理」的核心思路展开,分为4 种基础算法、1 种组合策略(分代收集)和1 种进阶分区算法,不同算法适配不同的内存分代 / 场景,以下是详细拆解:
一、基础垃圾回收算法(4 种核心)
这是 GC 的底层基础逻辑,所有复杂收集器均基于这些算法组合 / 优化。
| 算法类型 | 核心步骤 | 核心优点 | 核心缺点 | 适用区域 / 典型收集器 |
|---|---|---|---|---|
| 标记 - 清除(Mark-Sweep) | 1. 标记:通过可达性分析标记所有存活对象;2. 清除:遍历堆,回收未标记的垃圾对象 | 实现简单、不移动对象 | 1. 内存碎片严重;2. 效率低(遍历全堆) | 老年代 / CMS 收集器 |
| 复制算法(Copying) | 1. 划分:将内存分为 2 块(新生代优化为 Eden:S0:S1=8:1:1);2. 复制:用满后标记存活对象,复制到空闲区域;3. 清空:销毁原区域所有内存 | 1. 无内存碎片;2. 效率高(仅处理存活对象) | 内存利用率低(原始 1:1,优化后 90% 可用) | 新生代 / SerialGC、ParallelGC |
| 标记 - 整理(Mark-Compact) | 1. 标记:同标记 - 清除;2. 整理:将所有存活对象移动到内存一端(地址连续);3. 清除:回收边界外的所有内存 | 1. 无内存碎片;2. 内存利用率 100% | 效率低(移动对象 + 更新引用) | 老年代 / G1(老年代)、Serial Old |
| 标记 - 删除(Mark-Delete) | (非主流,仅嵌入式 JVM 使用)标记后直接删除垃圾对象,不整理 | 实现极简 | 碎片极严重、仅适配小内存 | 极小内存场景 / 嵌入式 JVM |
关键补充(基础算法):
- 标记 - 清除:是最早期算法,CMS 收集器为优化其效率,将 “清除” 拆分为 “初始标记→并发标记→重新标记→并发清除”,减少 STW(停止世界)时间;
- 复制算法:新生代的核心优化(8:1:1)是因为 “对象朝生夕死”,Eden 区满时仅需复制少量存活对象到 Survivor 区,利用率从 50% 提升到 90%;
- 标记 - 整理:是老年代的 “终极选择”,虽效率低,但能避免碎片导致的频繁 Full GC。
二、组合策略:分代收集算法(Generational Collection)
这不是独立算法,而是基于「分代假说」的组合策略,是 JVM 默认的 GC 核心逻辑。
1. 分代假说(核心依据)
- 假说 1:绝大多数对象 “朝生夕死”(新生代对象存活时间极短,回收频率高);
- 假说 2:存活对象会逐渐晋升到老年代(老年代对象存活时间长,回收频率低)。
2. 核心实现
- 新生代:用「复制算法」(存活对象少,复制成本低,无碎片);
- 触发 Minor GC:Eden 区满时,复制存活对象到 S0 区;下次 Minor GC 复制到 S1 区,多次存活后晋升老年代;
- 老年代:用「标记 - 清除」或「标记 - 整理」(存活对象多,复制成本高,优先避免移动对象);
- 触发 Major GC/Full GC:老年代空间不足时,回收老年代(Full GC 会同时回收新生代 + 老年代)。
3. 优势
兼顾 GC 效率和内存利用率:新生代用复制保证快回收,老年代用标记 - 清除 / 整理避免内存浪费。
三、进阶算法:分区收集算法(Region-Based)
为解决 “大内存场景(堆> 4G)下 STW 时间过长” 的问题,衍生出的分区策略,代表是 G1、ZGC、Shenandoah。
1. 核心思路
- 将整个堆划分为多个大小相等的独立 Region(默认 1~32MB);
- 每个 Region 可动态标记为 Eden、Survivor、Old 类型(打破传统 “新生代 / 老年代物理隔离”);
- 优先回收「垃圾占比最高的 Region」(Garbage-First,G1 名称由来),减少单次 GC 的停顿时间。
2. 实现逻辑(以 G1 为例)
- 标记:遍历所有 Region,标记存活对象;
- 筛选:计算每个 Region 的垃圾占比,排序出 “收益最高” 的 Region(回收后释放内存最多);
- 回收:对选中的 Region,用「复制算法」将存活对象复制到空闲 Region,清空原 Region;
- 整理:老年代 Region 回收后自动整理,避免碎片。
3. 核心优势
- 可控停顿:可设置最大 STW 时间(如
-XX:MaxGCPauseMillis=200),JVM 自动调整回收的 Region 数量; - 适配大内存:堆内存从几 G 到上百 G 均可高效回收(ZGC/Shenandoah 甚至支持 TB 级堆);
- 全堆统一管理:打破新生代 / 老年代的物理隔离,回收更灵活。
四、核心总结
- 算法演变逻辑:标记 - 清除(碎片多)→ 复制(无碎片但浪费)→ 标记 - 整理(无碎片不浪费)→ 分代(组合适配)→ 分区(大内存优化);
- 核心适配原则:
- 新生代(对象存活率低)→ 复制算法;
- 老年代(对象存活率高)→ 标记 - 清除 / 标记 - 整理;
- 大内存场景→ 分区算法(G1/ZGC);
- 实际收集器的算法组合:
- SerialGC:新生代复制 + 老年代标记 - 整理;
- CMS:老年代标记 - 清除(并发);
- G1:全堆分区 + 新生代复制 + 老年代标记 - 整理。
如果需要,可补充「各 GC 算法对应的 JVM 参数配置」或「算法性能对比(吞吐量 / 停顿时间)」,方便实战调优。