垃圾收集器

Serial 收集器<新生代/单线程/复制算法/响应速度优先>

  • Serial(串行)收集器是最基本、发展历史最悠久的收集器,它是采用复制算法新生代收集器
  • 它在进行垃圾收集时,必须暂停其他所有的工作线程,直至Serial收集器收集结束为止(STW,“Stop The World”)。

Serial Old 收集器<老年代/单线程/标记-整理算法/响应速度优先>

  • Serial Old 是 Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”(Mark-Compact)算法。

Parallel Scavenge 收集器<新生代/多线程/复制算法/吞吐量优先>

  • Parallel Scavenge收集器也是一个并行的多线程新生代收集器,它也使用复制算法
  • Parallel Scavenge收集器还提供了一个参数-XX:+UseAdaptiveSizePolicy,这是一个开关参数,打开参数后,就不需要手工指定新生代的大小(-Xmn)、Eden和Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种方式称为GC自适应的调节策略(GC Ergonomics)
  • 自适应调节策略也是Parallel Scavenge收集器与ParNew收集器的一个重要区别。

Parallel Old收集器<老年代/多线程/标记-整理算法/吞吐量优先>

  • Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多线程“标记-整理”算法。
  • 注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器。

ParNew 收集器<新生代/多线程/复制算法/响应速度优先>

  • ParNew收集器就是Serial收集器的多线程版本,它也是一个新生代收集器
  • 除了Serial收集器外,目前只有它能和CMS收集器(Concurrent Mark Sweep)配合工作。

CMS 收集器<老年代/多线程/标记-清除算法/响应速度优先>

  • CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,它非常符合那些集中在互联网站或者B/S系统的服务端上的Java应用,这些应用都非常重视服务的响应速度。从名字上(“Mark Sweep”)就可以看出它是基于“标记-清除”算法实现的。
  • 标记-清除算法导致的空间碎片 CMS是一款基于“标记-清除”算法实现的收集器,这意味着收集结束时会有大量空间碎片产生。

CMS收集器工作的整个流程分为以下4个步骤:

  • 初始标记(CMS initial mark):仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要“Stop The World”。
  • 并发标记(CMS concurrent mark):进行GC Roots Tracing的过程,在整个过程中耗时最长。
  • 重新标记(CMS remark):为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。此阶段也需要“Stop The World”。
  • 并发清除(CMS concurrent sweep)

G1 收集器

  • G1在使用时,Java堆的内存布局与其他收集器有很大区别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,而都是一部分Region(不需要连续)的集合
  • 垃圾收集器都存在 Stop The World 的问题,G1对这个问题进行了优化,G1对整个新生代和老年代一起回收,把堆划分为多个大小相等的独立区域region,使得每个region可以单独进行垃圾回收,通过记录每个region垃圾回收时间以及回收所获得的空间,并维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的region。
  • 并行与并发 G1 能充分利用多CPU、多核环境下的硬件优势,使用多个CPU来缩短“Stop The World”停顿时间,部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让Java程序继续执行。
  • 分代收集 与其他收集器一样,分代概念在G1中依然得以保留。虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但它能够采用不同方式去处理新创建的对象和已存活一段时间、熬过多次GC的旧对象来获取更好的收集效果。
  • 空间整合 G1从整体来看是基于“标记-整理”算法实现的收集器,从局部上来看是基于“复制”算法实现的。这意味着G1运行期间不会产生内存空间碎片,收集后能提供规整的可用内存。此特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。
  • 可预测的停顿 这是G1相对CMS的一大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了降低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在GC上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。
垃圾收集器 新生代/老年代 单线程/多线程 垃圾回收算法 目标
Serial Young Single-Thread 复制 响应速度优先
Serial Old Old Single-Thread 标记-整理 响应速度优先
Parallel Scavenge Young Multi-Thread 复制 吞吐量优先
Parallel Old Old Multi-Thread 标记-整理 吞吐量优先
ParNew Young Multi-Thread 复制 响应速度优先
CMS Old Multi-Thread 标记-清除 响应速度优先
G1 Both Multi-Thread 局部复制 / 整体标记-整理 响应速度优先