0%

JVM - 04 java垃圾收集器:串行/并行收集器

串行收集器使用单线程来执行所有的垃圾收集工作。
并行收集器(也称吞吐量收集器,Throughput Collector)使用多线程并行执行垃圾收集操作。

串行收集器

(1) Serial GC收集器(串行)

Serial GC用单线程处理所有垃圾回收工作,”单线程”不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,并且它在垃圾回收时,必须暂停其它所有的工作线程(称为”Stop The World”),直到它收集结束。
Serial GC在整个扫描和复制过程中均采用单线程方式进行,更加适合于单CPU、新生代空间较小及对暂停时间要求不是非常高的应用上。也是Client级别(CPU核数小于2或物理内存小于2G)或32位windows机器上默认采用的GC方式。
可以使用-XX:+UseSerialGC打开。

(2) Serial Old收集器

Serial Old是Serial垃圾收集器旧生代版本,它同样是个单线程的收集器,使用标记-整理算法,这个收集器也主要是运行在Client默认的java虚拟机默认的旧生代垃圾收集器。
在Server模式下,主要有两个用途:

  1. 在JDK1.5之前版本中与新生代的Parallel Scavenge收集器搭配使用。
  2. 作为旧生代中使用CMS收集器的后备垃圾收集方案。

Alt text

并行收集器

(1) ParNew收集器

ParNew收集器其实就是serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为与Serial收集器一样。但它却是许多运行在Server模式下的首选新生代收集器,其中一个与性能无关的很重要原因是,除了Serial收集器外,目前只有它能与CMS收集器配合工作。
可采用以下参数启用ParNew收集器:
 -XX:+UseParNewGC新生代采用ParNew收集器,旧生代采用串行收集器。
 -XX:+UseConcMarkSweepGC新生代采用ParNew收集器,旧生代使用CMS。
CPU核数小于等于8时,并行的线程数为CPU核数。CPU核数大于8时,并行线程数=3+(CPU核数*5)/8,可用-XX:ParallelGCThreads=指定。(屈雄烈备注:oracle只提到On a machine with N processors the parallel collector uses N garbage collector threads;, 故CPU核数大于8时的并行线程数,这一点还待验证)。
Alt text

(2) Parallel Scavenge收集器(并行回收)

Parallel Scavenge GC是一个新生代收集器,使用复制copying算法,在扫描和复制是均采用多线程的方式来进行,并且并行回收GC为大的新生代回收做了很多优化(如动态调整Eden,S0,S1空间大小)。在多核CPU上其CPU耗时比串行时间短。适合于多CPU,对暂停时间要求较短的应用上。
并行回收是server级别(CPU核数超过2且物理内存超过2GB)的机器(32位windows除外)上默认采用的GC方式。
CPU核数小于等于8时,并行的线程数为CPU核数。CPU核数大于8时,并行线程数=3+(CPU核数*5)/8,可用-XX:ParallelGCThreads=指定。(屈雄烈备注:oracle只提到On a machine with N processors the parallel collector uses N garbage collector threads;, 故CPU核数大于8时的并行线程数,这一点还待验证)。
可采用以下参数启用并行回收收集器:
 -XX:+UseParallelGC新生代采用并行回收收集器,旧生代采用串行收集器。
 -XX:+UseParallelOldGC新生代和旧生代都采用并行回收收集器。
Parallel Scavenge收集器的特点是它的关注点与其它收集器不同,CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而parallel Scavenge收集器的目标则是达到一个可控制的吞吐量。吞吐量=程序运行时间/(程序运行时间 + 垃圾收集时间),虚拟机总共运行了100分钟。其中垃圾收集花掉1分钟,那吞吐量就是99%。
Parallel Scavenge收集提供两个参数用于精确控制吞吐量:
-XX:MaxGCPauseMillis:控制最大垃圾收集停顿时间,是一个大于0的毫秒数。
-XX:GCTimeRatio:直接设置吞吐量大小,是一个大于0小于100的整数,也就是程序运行时间占总时间的比率,默认值是99,即垃圾收集运行最大1%(1/(1+99))的垃圾收集时间。

(3) Parallel Old收集器

Parallel Old收集器是Parallel Scavenge的旧生代版本,使用多线程的标记-整理算法,在JDK1.6才开始提供。
在JDK1.6之前,新生代使用Parallel Scavenge收集器只能搭配旧生代的Serial Old收集器,只能保证新生代的吞吐量优先,无法保证整体的吞吐量,Parallel Old正是为了在旧生代同样提供吞吐量优先的垃圾收集器,如果系统对吞吐量要求比较高,可以优先考虑新生代Parallel Scavenge和旧生代Parallel Old收集器的搭配策略。

Alt text

收集器参数

串行收集器相关参数

参数 描述
-XX:+UseSerialGC -client时启用,其它情况下,默认不启用 使用串行垃圾收集器,打开此开关后,使用Serial + Serial Old的收集器组合进行内存回收
-XX:SurvivorRatio 默认值8,Eden与Survivor的占用比例。例如8表示,一个survivor区占用 1/8 的Eden内存,即1/10的新生代内存,因为新生代有2个survivor,即S1和S2
-XX:PretenureSizeThreshold 默认值0,表示无最大值。直接晋升到旧生代对象的大小,设置这个参数后,大于这个参数的对象将直接在旧生代分配
-XX:MaxTenuringThreshold=n 默认值15,晋升到旧生代的对象年龄,每次Minor GC之后,年龄就加1,当超过这个参数的值时进入旧生代

并行收集器相关参数

参数 描述
-XX:+UseParNewGC 打开此开关后,使用ParNew+Serial Old的收集器进行垃圾回收
-XX:+UseParallelOldGC 默认不启用,使用Parallel Scavenge + Parallel Old的收集器组合进行回收
-XX:ParallelGCThreads 设置并行GC进行内存回收的线程数,默认情况与CPU数相同,在CPU较多的情况下,设置较小的值也是合理的。
-XX:MaxGCPauseMillis=n 设置GC的最大停顿时间, 它是大于0的整数。收集器工作时,会调整JAVA堆大小或其它一些参数,尽可能将停顿时间控制在MaxGCPauseMillis内。
-XX:GCTimeRatio GC时间占总时间的比例,值是0~100的整数。默认值为99,即允许1%的GC时间,仅在使用Parallel Scavenge收集器时有效
-XX:UseAdaptiveSizePolicy 打开自适应GC策略。动态调整java堆中各个区域的大小以及进入旧生代的年龄等参数,以到达堆大小,吞吐量和停顿时间之间的平衡点。

这两类收集器都是分代收集器,代表了JVM GC发展的早期阶段的技术。随着硬件发展和应用需求的变化,更新的垃圾收集器(如G1、ZGC等)旨在提供更低的停顿时间和更好的并发性能。

– end –