垃圾收集器总结

118 阅读3分钟

垃圾收集器总结

常用垃圾收集器对比

垃圾收集器串行/并行/并发新生代/老年代算法目标适用场景
Serial串行新生代复制低延迟优先单 CPU 环境下的 Client 模式
Serial Old串行老年代标记-整理低延迟优先单 CPU 环境下的 Client 模式、CMS 的后备预案
Parllel Scavenge并行新生代复制吞吐量优先在后台运算而不需要太多交互的业务
Parallel Old并行老年代标记-整理吞吐量优先在后台运算而不需要太多交互的业务
ParNew并行新生代复制低延迟优先多 CPU 环境下,在 Server 模式与 CMS 配合使用
CMS并发老年代标记-清除低延迟优先内存不大的 Java 应用
G1并发both标记-整理+复制低延迟优先大内存的 Java 应用

常用垃圾收集器组合

  1. Serial + Serial Old:实现单线程的低延迟垃圾回收机制
  2. Parallel Scavenge + Parallel Old:实现多线程的高吞吐垃圾回收机制
  3. ParNew + CMS:实现多线程的低延迟垃圾回收机制
  4. G1:实现大内存 Java 应用的低延迟垃圾回收机制

如何选择垃圾收集器

  1. 吞吐量优先 or 低延迟优先

    1. 吞吐量优先

      目标是充分利用多核 CPU 资源,让 CPU 尽可能多地处理业务,可以选择 Parallel GC,Parallel Scavenge + Parallel Old 的方案。

    2. 低延迟优先

      目标是每次 GC 停顿时间尽量短,可以选择 CMS + ParNew 或直接使用 G1。

  2. 内存维度的考量

    1. 如果系统内存堆较大(超过 8G),同时希望整体来看平均 GC 时间可控,优先选择 G1。
    2. 如果内存很小,几百 MB,那使用什么 GC 其实影响都不大。
  3. 业务维度的考量

    1. 目前大部分 Java 应用系统,堆内存并不大(2G~4G),而且对 10ms 这种低延迟的 GC 暂停不敏感,也就是说处理一个业务流程,大概几百毫秒都是可以接受的, GC 暂停 50ms 还是 10ms 没多大区别。另一方面,系统的吞吐量反而往往是我们追求的重点,这时候就需要考虑采用并行 GC。
    2. 如果堆内存再大一些(比如超过 8G),则优先使用 G1。不然大内存下,一次 Full GC 的时间可能达到秒级别,业务上无法忍受。

垃圾收集技术发展脉络

  1. 串行 -> 并行

    充分利用多核 CPU 的优势,大幅降低 GC 停顿时间,提升吞吐量。

  2. 并行 -> 并发

    不只开多个 GC 线程并行回收,还将 GC 操作拆分为多个步骤,让很多繁重的任务和应用线程一起并发执行,减少了单次 GC 暂停持续的时间,这能有效降低业务系统的延迟。

  3. CMS -> G1

    G1 可以说是在 CMS 基础上进行迭代和优化开发出来的,将整个堆划分为多个小 Region 进行增量回收,这样就更进一步地降低了单次 GC 暂停的时间。

  4. G1 -> ZGC

    ZGC 号称无停顿垃圾收集器,这又是一次极大的改进。 ZGC 和 G1 有一些相似的地方,但是底层的算法和思想又有了全新的突破。