JVM-垃圾收集器详解

一:JDK1.7之后Hotspot虚拟机使用的垃圾收集器

如下图所示,若两个收集器之间存在连线,说明它们可以搭配使用。
JVM-垃圾收集器详解

二:Serial收集器

Serial收集器是最基本的,发展历史最悠久的收集器,是一个单线程的收集器,只会使用一个CPU或一条收集线程去完成垃圾收集工作,而且在进行垃圾收集时,必须暂停其他所有的工作线程,知道它收集结束。

暂停其他所有的工作线程,这个过程被称为“Stop The World”,由虚拟机在后头自动发起和自动完成,在用户不可见的情况下把用户正常工作的线程全部停止。
JVM-垃圾收集器详解
Serial收集器的优点是简单高效。

三:ParNew收集器

ParNew收集器是Serial收集器的多线程版本,使用多条线程进行垃圾收集,其他都与Serial收集器一样。
JVM-垃圾收集器详解

四:Parallel Scavenge收集器

Parallel Scavenge收集器是使用复制算法的,并行多线程收集器。该收集器的特点是达到一个可控制的吞吐量(吞吐量优先),吞吐量是CPU用于运行用户代码时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾回收时间)。

吞吐量高可用高效的利用CPU时间,尽快完成程序的运算任务,主要适合后台运算多而不需要太多交互的任务。

Parallel Scavenge收集器提供了两个参数精确控制吞吐量,分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis参数,以及直接设置吞吐量大小的-XX:GCTimeRatio参数。

参数-XX:UseAdaptiveSizePolicy,打开这个参数,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整各种参数以提高最适合的停顿时间或最大的吞吐量。

五:Serial Old收集器

Serial Old是Serial收集器的老年代版本,也是单线程的收集器,使用“标记-整理”算法。

在Server模式下,它主要有两个用途:一是在JDK1.5及以后的版本中,与Parallel Scavenge收集器搭配使用;二是作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用。

JVM-垃圾收集器详解

六:Parallel Old收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理算法”
JVM-垃圾收集器详解

七:CMS收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。基于“标记-清除”算法实现。

垃圾收集过程主要分为四个阶段:

初始标记
并发标记
重新标记
并发清除

初始标记、重新标记仍需要“Stop The World”,初始标记只标记GC roots 能直接关联的对象,速度快;并发标记就是进行GC Roots Tracing的过程,重新标记是为了修正并发标记期间因用户程序继续运行而导致标记发生变动的那部分对象的标记记录,这个阶段的停顿时间一般比初始标记稍长,但远比并发标记时间短。
JVM-垃圾收集器详解
CMS优点:并发收集,低停顿

CMS缺点

(1)对CPU资源敏感。面向并发设计的程序都对CPU资源比较敏感。在并发阶段,虽然不会导致用户线程停顿,但是因为占用了一部分线程(CPU资源)而导致应用程序变慢总吞吐量会降低。

(2)无法处理浮动垃圾,可能会出现“Concurrent Mode Failure”失败而导致另一次Full GC
因为并发清除阶段,用户线程还在运行,就可能会有新的垃圾产生,这部分垃圾出现在标记过程之后,只能留待下次GC回收,这部分垃圾称为“浮动垃圾”。

(3)产生大量空间碎片,因为使用的是标记-清除算法。

八:G1收集器

G1(Garbage-First)收集器是面向服务端应用的垃圾收集器。

优势

(1)并行与并发:充分利用多CPU,多核的优势,使用多个CPU来缩短Stop The World停顿时间。部分原本需要停顿java线程执行GC动作,G1收集器仍然可以使用并发的方式让java程序继续运行。

(2)分代收集:而且可以不需要其他收集器配合就能独立管理整个GC堆。

(3)空间整合:G1整体上是基于标记-整理算法实现,从局部(两个region之间)来看是基于复制算法实现,这意味着G1运行期间不会产生内存碎片。

(4)可预测停顿:这是相比CMS的一大优势,G1不仅能降低停顿时间,而且还能建立可预测停顿时间模型,指定在一个长度为M毫秒的时间片内,GC收集时间不得超过N毫秒。

G1垃圾收集过程

初始标记
并发标记
最终标记
筛选回收

初始标记标记GC Roots直接关联的对象,并修改TAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确的region(在使用G1收集器时,将java堆划分为多个大小相等的独立区域[region],虽然还保留新生代,老年代的概念,但两者不再是物理隔离了,它们都是一部分region[不需要连续]的集合)中创建新对象,这阶段需要停顿线程,但耗时很短。

并发标记从GC Roots开始对堆中对象进行可达性分析,找出存活对象,这阶段耗时较长,但可与用户线程并发执行。

最终标记修正在并发标记期间,因用户线程继续运行而导致的标记产生变动的那部分标记记录,虚拟机将这段时间对象变化记录在线程Remembered Set Logs里,最终标记时,将Remembered Set Logs的数据合并到Remembered Set 中,这阶段需要停顿线程,但可以并行执行。

筛选回收时,对各个region的回收价值(可回收的内存大小)和成本(回收耗费的时间)进行排序,根据用户期望的GC停顿时间制定回收计划。
JVM-垃圾收集器详解

九:垃圾收集器参数介绍

JVM-垃圾收集器详解
JVM-垃圾收集器详解

note:注意在讨论垃圾收集器的上下文语境中

并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍处于等待状态。

并发(Concurrent):指用户线程与垃圾收集线程同时执行(不一定是并行,可能是交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。