实际上,垃圾收集器(GC,Garbage Collector)是和具体 JVM 实现紧密相关的,不同厂商 (IBM、Oracle),不同版本的 JVM,提供的选择也不同。一般我们说的 JVM 指的就是 Oracle JDK 的 JVM。

  • 新生代收集器:Serial、ParNew、Parallel Scavenge
  • 老年代收集器:Serial Old、Parallel Old、CMS
  • 整堆收集器:G1

新生代收集器

Serial

  • 特点:
    • 采用复制算法
    • 单线程收集
  • 应用场景:
    • 简单高效(与其他收集器的单线程相比)
    • 对于限定单个CPU的环境来说,Serial收集器没有线程交互(切换)开销,可以获得最高的单线程收集效率
    • 在用户的桌面应用场景中,可用内存一般不大(几十M至一两百M),可以在较短时间内完成垃圾收集(几十MS至一百多MS),只要不频繁发生,这是可以接受的
  • 启用参数:-XX:+UseSerialGC

ParNew

  • 特点:
    • 除了多线程外,其余的行为、特点和Serial收集器一样
  • 应用场景:
    • 在Server模式下,ParNew收集器是一个非常重要的收集器,因为除Serial外,目前只有它能与CMS收集器配合工作
    • 在单个CPU环境中,不会比Serial收集器有更好的效果,因为存在线程交互开销
  • 启用参数:-XX:+UseParNewGC

Parallel Scavenge

  • 特点:
    • 采用复制算法
    • 多线程收集
  • 应用场景:
    • 高吞吐量为目标,即减少垃圾收集时间,让用户代码获得更长的运行时间
    • 当应用程序运行在具有多个CPU上,对暂停时间没有特别高的要求时,即程序主要在后台进行计算,而不需要与用户进行太多交互
  • 启用参数:-XX:+UseParallelGC
  • 其他参数:
    • 设置垃圾收集时间占总时间的比率:-XX:GCTimeRatio=N // GC 时间和用户时间比例 = 1 / (N+1)
    • 控制最大垃圾收集停顿时间:-XX:MaxGCPauseMillis=value //大于0的毫秒数

老年代收集器

CMS

  • 特点:
    • 基于”标记-清除”算法(不进行压缩操作,产生内存碎片),以获取最短回收停顿时间为目标
    • 并发收集、低停顿
    • 需要更多的内存
  • 应用场景:
    • 与用户交互较多的场景
    • 希望系统停顿时间最短,注重服务的响应速度
  • 启用参数:-XX:+UseConcMarkSweepGC,年轻代自动开启ParNew: -XX:-UseParNewGC

从 Java 9 开始,不推荐使用 CMS 垃圾收集器。因此,如果我们尝试使用,JVM 将输出警告消息。此外,Java 14 完全放弃了 CMS 支持

Serial Old

  • 特点
    • 采用”标记-整理”算法
    • 单线程收集
  • 应用场景:
    • 主要用于Client模式
  • 启用参数:CMS失败时启用

Parallel Old

  • 特点:
    • 采用”标记-整理”算法
    • 多线程收集
  • 应用场景:
    • JDK1.6及之后用来代替老年代的Serial Old收集器,特别是在Server模式,多CPU的情况下
    • 这样在注重吞吐量以及CPU资源敏感的场景,就有了Parallel Scavenge加Parallel Old收集器的”给力”应用组合
  • 启用参数:-XX:+UseParallelOldGC

整堆收集器

G1

  • 特点:
    • 并行与并发
    • 分代收集,收集范围包括新生代和老年代
    • 结合多种垃圾收集算法,空间整合,不产生碎片(从整体看,是基于标记-整理算法;从局部(两个Region间)看,是基于复制算法)
    • 可预测的停顿:低停顿的同时实现高吞吐量
  • 应用场景:
    • 面向服务端应用,针对具有大内存、多处理器的机器
    • 最主要的应用是为需要低GC延迟,并具有大堆的应用程序提供解决方案
  • 启用参数:-XX:+UseG1GC