上面的三个属于用于新生代的收集器,下面是老年代,有连线代表可以互相配合使用。
Serial收集器
Serial收集器是最基本、发展历史最悠久的收集器,是一个单线程的收集器,其并不仅仅代表只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集的时候,必须暂停其他所有的工作线程,直至它收集结束。
优点:简单而高效,对于限定单个CPU环境来说,由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。是运行在Client模式下的默认新生代收集器。
ParNew收集器
其实就是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为如控制参数、收集算法、Stop The World、对象分配规则和回收策略等都与前者一样。是许多运行在Server模式下的虚拟机中首选的新生代收集器,其中一个与性能无关的原因是,它能与CMS收集器配合工作。
在单CPU的情况下,它的效率绝对比不上Serial收集器,但是多CPU中,其百分百超过Serail收集器。
解释两个名词:
- 并行(Parallel):指多条垃圾收集器并行工作,但此时用户线程仍然处于等待状态。
- 并发(Concurrent):指用户线程与垃圾收集器同时执行(不一定并行,可能会交替执行),用户程序在继续执行,而垃圾收集程序运行于另一个CPU上。
Parallel Scavenge收集器
Parallel Scavenge收集器是一个新生收集器,它也是使用复制算法的收集器,又是并行的多线程收集器,其特点是它的关注点与其他收集器不同,其他收集器的关注点是尽可能的缩短垃圾收集时用户线程的停顿时间,而它的关注点是达到一个可以控制的吞吐量(Throughput)。即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)。被称为“吞吐量优先”收集器。
Serial Old收集器
是Serial收集器的老年代版本,同样是一个单线程收集器,使用“标记-整理”算法,其主要意义也是在于给Client模式下的虚拟机使用。如果在Server模式下,有两大用处:一是在JDK 1.5以及之前的版本中与Parallel Scavenge收集器搭配使用,二是作为CMS收集器的后备预案。
Parallel Old收集器
是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。与Parallel Scavenge收集器联合使用,用于注重吞吐量和CPU资源敏感的场合。
CMS收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。顾名思义,是基于“标记-清除”算法实现的,其运作过程分为下面四个过程:
- 初始标记(CMS initial mark)
- 并发标记(CMS concurrent mark)
- 重新标记(CMS remark)
- 并发消除(CMS concurrent sweep)
其中,初始标记、重新标记这两个步骤需要“Stop The World”,初始标记只是标记一下GC Roots能直接关联到的对象,速度很快;并发标记是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,其停顿时间一般比初始标记阶段稍长一些,但远比并发标记时间短。
但是,整个过程中耗时最长的并发标记和并发消除过程收集器都可以与用户线程一起工作,所以,总体来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。
CMS的优点:并发收集、低停顿,但是其有3个明显的缺点:
- CMS收集器对CPU资源非常敏感。其实,面向并发设计的程序都对CPU资源比较敏感。在并发阶段,虽然不会使用户线程停顿,但由于占用了一部分线程(或者说CPU资源)而导致应用程序变慢,总吞吐量降低。
- 无法处理浮动垃圾,可能会出现“Concurrent Mode Failure”而导致另一次Full GC的产生。由于CMS并发清理阶段用户线程还在运行,伴随程序运行自然还会有新的垃圾不断产生。这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好等待下一次GC时再清理掉。这一部分垃圾称为“浮动垃圾”。
- 由于其采用“标记-清除”算法,收集结束后会有大量空间碎片产生。空间碎片过多,会给大对象分配带来很大麻烦。
G1收集器
G1(Garbage-First)收集器是当今收集器技术发展的最前沿成果之一,是一款面向服务端应用的垃圾收集器。具备如下特点:
- 并行与并发:G1收集器能充分利用多CPU、多核环境下的硬件优势,使用多个CPU(或CPU核心)来缩短Stop The World停顿的时间,部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让Java程序继续执行。
- 分代收集:虽然G1可以不需要其他收集器哦配合,但它能采用不同方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。
- 空间整合:从整体来看,G1是基于“标记-整理”算法实现的收集器,从局部来看(两个Region之间)是基于复制算法实现的。无论如何,这意味着G1运作期间不会产生内存空间碎片,有利于程序长时间运行。
- 可预测的停顿:这是G1相对于CMS的另一大优势,消耗在垃圾收集上的时间不得超过用户设置的N毫秒,这几乎已经是实时Java的垃圾收集器的特征了。
之所以G1能建立可预测的停顿时间模型,是因为它可以有计划的避免在整个Java堆中进行全区域的垃圾收集。G1根据各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需要时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region(也就是Garbage-First的由来)。
如果不计算维护Remembered Set的操作,G1收集器哦运作大致分为以下几个步骤:
- 初始标记
- 并发标记
- 最终标记
- 筛选回收