深入理解JAVA虚拟机读书笔记:垃圾收集器

上一篇文章我们讲了很多关于垃圾回收的算法,这一篇我们一起来看看垃圾收集器是如何来实现他们的。

一、垃圾收集器的组合

在jdk7后,HotSpot虚拟机所有的垃圾收集器和组合如下。
在这里插入图片描述

1、图中他们所在的区域表明他们是属于新生代收集器还是老年代收集器:

新生代收集器:Serial、ParNew、ParallelScavenge
老年代收集器:CMS、SerialOld、ParallelOld
整堆收集器:G1

2、图中连线则表明他们可以搭配使用:

Serial/SerialOld、Serial/CMS、ParNew/SerialOld、ParNew/CMS、ParallelScavenge/SerialOld、ParallelScavenge/ParallelOld

3、其中SeralOld作为CMS发生Current Mode Failure的后备预案。

二、垃圾收集器

1、Serial收集器

Serial(串行)收集器是一个单线程收集器。
1、收集算法:复制算法
2、优缺点
优点:简单而高效,对于限定单个CPU环境来说,没有上下文切换的开销。
缺点:必须停掉所有其他工作线程。
3、应用场景
用户的桌面应用中,虚拟机的可用内存不大,新生代较小的情况下,可以在较短的时间内完成垃圾收集。
4、设置参数
-XX:+UseSerialGC:添加改参数来显式的使用Serial(串行)收集器。
Serial/Serial组合收集如下:
在这里插入图片描述

2、ParNew收集器

ParNews收集器是Serial收集器的多线程版本。除了多线程外,其余行为和Serial收集器一样。
1、应用场景
在Server模式下,ParNew收集器是一个非常重要的收集器,因为除了Serial收集器,新生代收集器只有ParNew收集器能和CMS收集器配合使用。
2、设置参数
-XX:+UseConcMarkSweepGC:使用CMS作为老年代收集器默认使用ParNew收集器作为新生代收集器。
-XX:+UseParNewGC:强制使用ParNew收集器作为新生代收集器。
-XX:ParallelGCThreads:限制垃圾收集的线程数,默认和CPU数量相同。
ParNew/SerialOld组合如下:
在这里插入图片描述

3、Parallel Scavange收集器

Parallel Scavenge收集器是一个新生代多线程收集器。目标是达到一个可控制的吞吐量,也成为吞吐量收集器(Throughput Collector)。
1、收集算法:复制算法
2、优缺点
优点:高吞吐量可以高效率地利用CPU时间,尽快完成程序的运算任务。
缺点:不关注停顿时间。
3、应用场景
当应用程序运行在具有多个CPU上时,对暂停时间没有特别要求,程序主要用于后台运算,不需要太多用户交互的任务。
4、设置参数
Parallel Scavange收集器提供了两个参数用于精确控制吞吐量。
-XX:MAXGCpauseMillss:控制最大垃圾收集停顿时间。
MAXGCPauseMillis设置得稍小,停顿时间会缩短,但是同时也牺牲了吞吐量。GC停顿时间缩短是牺牲了吞吐量和新生代的空间来换取的。
-XX:GCTimeRatio:设置吞吐量。
大于0小于100的证书,默认值为99,也就是允许最大GC时间占总时间的1%.
-XX:UseAdaptiveSizePolicy:自适应大小策略。
这是一个开关参数,当这个参数打开之后,就不需要手工指定新生代大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象大小(-XX:PretenureSizeThreshold)等细节参数了。只需要把基本内存数据设置好(如-Xmx设置最大堆),然后使用MaxGCPauseMillis参数或者GCTimeRatio参数给虚拟机设立一个优化目标,具体细节参数的调解工作就由虚拟机自动完成。
5、另外提一个重要公式 吞吐量 = 用户代码运行时间/(用户代码运行时间+GC收集时间)

4、Serail Old收集器

Serail收集器的老年代版本,同样是一个单线程收集器。
1、收集算法:标记整理
2、适用场景
JDK 1.5以及之前与Parallel Scavange搭配使用,另一个用户就是作为CMS收集器的后预案,在并发收集Concurrent Mode Failure时使用。
Serial/Serial Old收集器运行示意图如下:
在这里插入图片描述

5、Parallel Old收集器

Parallel Scavange收集器的老年代版本。多线程收集器。
1、收集算法:标记整理
2、设置参数
-XX:+UseParallelOldGC:指定使用Parallel Old收集器;
3、适用场景
JDK 1.5以及之前,Parallel Scavange作为新生代收集器只能与Serial Old搭配使用,吞吐量甚至不一定有ParNew/CMS组合给力,注重吞吐量以及CPU资源敏感优先考虑Parallel Scavange/Parallel Old组合。
Parallel Scavenge/Parallel Old收集器运行示意图如下:
在这里插入图片描述

6、CMS(Concurrent Mark Sweep)收集器

CMS收集器是一种以获取最短回收停顿时间为目标的收集器。
1、收集算法:标记——清除
2、优缺点
优点:系统停顿时间短。
缺点:1)对CPU资源敏感 默认启动的线程数是(CPU数量+3)/4,并发收集不少于25%的CPU资源,也就是说CPU数量越多启动的线程就会相对比例较小,所以建议多CPU的情况下使用。当CPU较少时,对用户程序的影响就会变得很大了。
2)无法处理浮动垃圾,可能出现Concurrent Mode Failure失败。在并发清理时用户程序自然还会产生新的垃圾,CMS无法再当次手机中处理掉它们,这一部分垃圾就称为“浮动垃圾”。也由于在垃圾收集阶段用户线程还需要运行,所以需要预留足够的内存空间给用户线程使用,如果预留内存空间无法满足程序需要,就会出现Concurrent Mode Failure失败,虚拟机将启动后备预案,临时使用Serail Old收集器来重新进行老年代的垃圾收集。
3)基于标记——清除算法,会有大量的空间碎片产生。
3、收集过程
1)初始标记:这个阶段需要停顿用户线程,就是简单标记一下GC Roots能直接关联的对象。
2)并发标记:这个阶段可以用用户线程并发执行,就是GC Roots Tracing(从GC Roots跟踪对象)的过程。
3)重新标记:这个阶段需要停顿用户线程,修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分记录,比初始标记时间要长一些,但没有并发标记时间长。
4)并发清理:回收所有垃圾对象。
4、设置参数
-XX:useConcMarkSweepGC:指定使用CMS收集器;
-XX:CMSInitiatingOccupancyFraction:老年代使用空间百分比激活CMS收集。
-XX:UseCMSCompactAtFullCollection:默认开启,顶不住要进行FullGC时整合内存碎片。
-XX:CMSFullGCsBeforeCompaction:和上个参数搭配使用,执行多少次不压缩的FullGC后,跟着来一次压缩的。默认为0。
5、适用场景
目前很大一部分Java应用几种在互联网站或者B/S系统的服务端,这类应用尤其重视服务的响应速度,希望系统停顿时间短,给用户带来较好的体验。
CMS收集器运行示意图如下:
在这里插入图片描述

G1收集器比较特殊,我们留到下一篇博客详细讲解G1收集器。

猜你喜欢

转载自blog.csdn.net/f191501223/article/details/84572788