新生代和老年代的 GC 算法有哪些?

一则或许对你有用的小广告

欢迎 加入小哈的星球 ,你将获得: 专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目: 《Spring AI 项目实战(问答机器人、RAG 增强检索、联网搜索)》 正在持续爆肝中,基于 Spring AI + Spring Boot3.x + JDK 21...点击查看;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot3.x + JDK 17...点击查看项目介绍; 演示链接: http://116.62.199.48:7070/;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/

面试考察点

  1. 考察对 JVM 垃圾收集(GC)基本原理的理解:面试官想知道你是否清楚 JVM 为什么采用分代收集(Generational Collection)以及不同代的特点。
  2. 考察对具体 GC 算法的掌握程度:不仅仅是知道算法名字,更要理解其核心思想、工作原理以及优缺点。
  3. 考察算法与具体垃圾收集器的关联能力:面试官希望你能将抽象的算法与实际的垃圾收集器(如 Serial、Parallel、CMS、G1)对应起来,知道哪些收集器在新生代/老年代使用了什么算法。
  4. 考察对 GC 发展趋势的认知:通过你对 G1、ZGC 等新收集器的了解,判断你是否关注 JVM 的最新演进。

核心答案

JVM 的新生代和老年代分别采用不同的垃圾收集算法,以适应各自区域的对象存活率内存布局特点。

  • 新生代(Young Generation):主要采用 复制算法(Copying)。因为新生代对象 “朝生夕死”,存活率低,复制算法只需复制少量存活对象,效率高且不会产生内存碎片。
  • 老年代(Old Generation):主要采用 标记-清除算法(Mark-Sweep)标记-整理算法(Mark-Compact)。老年代对象存活率高,复制算法不划算,所以通过标记来识别垃圾,然后直接清除或进行内存整理。

深度解析

1. 新生代复制算法详解

  • 原理:将内存分为一块较大的 Eden 空间和两块较小的 Survivor 空间(默认比例 8:1:1)。每次使用 Eden 和其中一块 Survivor(From)。回收时,将 Eden 和 From 中存活的对象复制到另一块 Survivor(To),然后一次性清理掉 Eden 和 From 空间。如果 To 空间不够,存活对象会通过 分配担保 直接进入老年代。
  • 优点:实现简单,运行高效,不会产生内存碎片。
  • 缺点:需要预留一块空闲的 Survivor 作为复制目标,存在空间浪费;对象存活率较高时,复制操作开销变大。
  • 具体收集器
    • Serial / ParNew:均采用这种典型的复制算法。
    • Parallel Scavenge:也是复制算法,但更注重吞吐量控制。

2. 老年代标记-清除与标记-整理算法

  • 标记-清除(Mark-Sweep)
    • 原理:先标记出所有存活对象,然后统一回收未被标记的对象。
    • 优点:实现简单,不需要移动对象。
    • 缺点:会产生大量内存碎片,导致后续大对象分配失败而提前触发 Full GC;标记和清除两个过程的效率都不高。
    • 代表收集器CMS(Concurrent Mark Sweep) 老年代收集器基于标记-清除算法。
  • 标记-整理(Mark-Compact)
    • 原理:标记阶段与标记-清除相同,但后续不是直接清除,而是将所有存活对象向内存一端移动,然后直接清理边界以外的内存。
    • 优点:解决了内存碎片问题,内存利用率高,分配大对象更顺畅。
    • 缺点:移动对象需要暂停用户线程(Stop The World),如果老年代对象很多,停顿时间可能较长。
    • 代表收集器
      • Parallel Old:老年代采用标记-整理算法,与 Parallel Scavenge 搭配追求高吞吐量。
      • Serial Old:同样采用标记-整理算法。

3. 新趋势:分区收集器中的算法演变

  • G1(Garbage First)收集器:虽然保留了新生代和老年代的概念,但物理上不再连续,而是将堆划分为多个大小相等的 Region。G1 整体上采用 标记-整理算法,从局部(两个 Region 之间)看又是复制算法。它避免了在整个老年代进行整理,从而降低了停顿时间。
  • ZGC(Z Garbage Collector):同样基于 Region 布局,通过染色指针和读屏障等技术实现几乎全部的并发收集,其核心算法也融合了复制和标记的思想,但实现细节更为复杂。

4. 常见误区

  • 误区一:认为所有垃圾收集器都严格区分新生代和老年代算法。
    • 实际上,像 G1、ZGC 这种新一代收集器,虽然仍然有分代逻辑(G1 明确分代,ZGC 在后续版本中也开始支持分代),但算法实现已经高度融合,不再是简单的“新生代只用复制、老年代只用标记-整理”。
  • 误区二:混淆 “标记-清除” 与 “标记-整理” 的适用场景。
    • 如果老年代使用 CMS(标记-清除),必须预留足够空间或搭配备用方案(如启用 -XX:+UseCMSCompactAtFullCollection),否则碎片问题可能引发频繁 Full GC。

总结

JVM 通过分代收集,让新生代利用复制算法的高效处理短期对象,让老年代利用标记-清除或标记-整理算法应对长期存活对象。理解这些基础算法,是掌握各种垃圾收集器工作原理的基石,也是 JVM 性能调优的必备知识。