新生代收集器

上一篇介绍了垃圾收集器的分类。这一篇主要介绍三种新生代垃圾收集器。

Serial(-XX:+UseSerialGC)

  1. Serial 回收器是最基本的新生代垃圾回收器,是单线程的垃圾回收器,它是采用**复制算法**。由于垃圾清理时,Serial 回收器不存在线程间的切换,因此,特别是在单 CPU 的环境下,它的垃圾清除效率比较高。对于 Client 运行模式的程序,选择 Serial 回收器是一个不错的选择。<br />** **** 它在进行垃圾收集时,必须暂停其他所有的工作线程,直至Serial收集器收集结束为止(“Stop The World”)**。这项工作是由虚拟机在后台自动发起和自动完成的,在用户不可见的情况下把用户正常工作的线程全部停掉,这对很多应用来说是难以接收的。

ParNew(-XX:+UseParNewGC)

属于多线程垃圾回收器(吞吐量优先)
** ParNew收集器就是Serial收集器的多线程版本,它也是一个新生代收集器**。除了使用多线程进行垃圾收集外,其余行为包括Serial收集器可用的所有控制参数、收集算法(复制算法)、Stop The World、对象分配规则、回收策略等与Serial收集器完全相同,两者共用了相当多的代码。
ParNew收集器的工作过程如下图(老年代采用Serial Old收集器):
WX20191215-204923@2x.png

  1. ParNew收集器除了使用多线程收集外,其他与Serial收集器相比并无太多创新之处,但它却是许多运行在Server模式下的虚拟机中首选的新生代收集器,其中有一个与性能无关的重要原因是,**除了Serial收集器外,目前只有它能和CMS收集器(Concurrent Mark Sweep)配合工作**,CMS收集器是JDK 1.5推出的一个具有划时代意义的收集器,具体内容将在下一篇进行介绍。<br /> ParNew 收集器在**单CPU的环境**中绝对不会有比Serial收集器有更好的效果,甚至由于存在线程交互的开销,该收集器在通过超线程技术实现的两个CPU的环境中都不能百分之百地保证可以超越。在**多CPU环境**下,随着CPU的数量增加,它对于GC时系统资源的有效利用是很有好处的。它默认开启的收集线程数与CPU的数量相同,在CPU非常多的情况下可使用**-XX:ParallerGCThreads**参数设置。

Parallel Scavenge(-XX:+UseParallelGC)

  1. Parallel Scavenge 回收器属于多线程的回收器。<br />但与ParNew不同的是:
  1. ParNew回收器是通过控制垃圾回收的线程数来进行参数调整,而Parallel Scavenge回收器更关心的是程序运行的吞吐量。即一段时间内,用户代码运行时间占总运行时间的百分比。
  2. 自适应调节策略也是Parallel Scavenge 垃圾收集器与ParNew收集器的一个重要区别。【自适应调节策略:虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最适合的停顿时间(

    -XX:MaxGCPauseMillis)或最大吞吐量】。

一句话概括:串行收集器在新生代和老年代并行化。
停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验。而高吞吐量则可以高效率地利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务
Parallel Scavenge收集器除了会显而易见地提供可以精确控制吞吐量的参数,还提供了一个参数
-XX:+UseAdaptiveSizePolicy,这是一个开关参数,打开参数后,就不需要手工指定新生代的大小(-Xmn)、Eden和Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种方式称为GC自适应的调节策略(GC Ergonomics)。自适应调节策略也是Parallel Scavenge收集器与ParNew收集器的一个重要区别。
注意:Parallel Scavenge收集器无法与CMS收集器配合使用,所以在JDK 1.6推出Parallel Old之前,如果新生代选择Parallel Scavenge收集器,老年代只有Serial Old收集器能与之配合使用。

Parallel Scavenge收集器的工作过程如下图(老年代采用Parallel Old收集器):
WX20191215-205930@2x.png