一:JDK1.7之后Hotspot虚拟机使用的垃圾收集器
如下图所示,若两个收集器之间存在连线,说明它们可以搭配使用。
二:Serial收集器
Serial收集器是最基本的,发展历史最悠久的收集器,是一个单线程的收集器,只会使用一个CPU或一条收集线程去完成垃圾收集工作,而且在进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。
暂停其他所有的工作线程,这个过程被称为“Stop The World”,由虚拟机在后头自动发起和自动完成,在用户不可见的情况下把用户正常工作的线程全部停止。
Serial收集器的优点是简单高效。
三:ParNew收集器
ParNew收集器是Serial收集器的多线程版本,使用多条线程进行垃圾收集,其他都与Serial收集器一样。
四: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时使用。
六:Parallel Old收集器
Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理算法”
七:CMS收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。基于“标记-清除”算法实现。
垃圾收集过程主要分为四个阶段:
初始标记
并发标记
重新标记
并发清除
初始标记、重新标记仍需要“Stop The World”,初始标记只标记GC roots 能直接关联的对象,速度快;并发标记就是进行GC Roots Tracing的过程,重新标记是为了修正并发标记期间,因用户程序继续运行,而导致标记发生变动的那部分对象的标记记录,这个阶段的停顿时间一般比初始标记稍长,但远比并发标记时间短。
CMS优点:并发收集,低停顿
CMS缺点:
(1)对CPU资源敏感。面向并发设计的程序都对CPU资源比较敏感。在并发阶段,虽然不会导致用户线程停顿,但是因为占用了一部分线程(CPU资源)而导致应用程序变慢总吞吐量会降低。
(2)无法处理浮动垃圾,可能会出现“Concurrent Mode Failure”失败而导致另一次Full GC。
因为并发清除阶段,用户线程还在运行,就可能会有新的垃圾产生,这部分垃圾出现在标记过程之后,只能留待下次GC回收,这部分垃圾称为“浮动垃圾”。
(3)产生大量空间碎片,因为使用的是标记-清除算法。
八:G1收集器
G1(Garbage-First)收集器是面向服务端应用的垃圾收集器。
在G1之前的所有收集器,垃圾收集范围要么是新生代,要么是老年代,要么是整个java堆,而G1能对堆的任意部分组成回收集进行回收,衡量标准不再是属于哪个分代,而是哪块内存中存放的垃圾数量最多,回收效益最大。
G1的堆内存布局是基于region的,把java堆划分成多个大小相等的独立区域(region),每个region可以根据需要扮演新生代Eden,survivor空间,或者老年代,收集器能采取相应的策略进行垃圾收集。
region中有个叫humongous区域,专门存储大对象,G1认为对象大小超过region容量一半则判定为大对象。对于那些超过了整个region容量的对象,将会被存放在N个连续的humongous region之中,G1大多数行为把humongous当作老年代的一部分来看待。
G1之所以能建立可预测的停顿时间模型,是因为它将region作为单次回收的最小单元,即每次回收的内存空间都是region大小的整数倍,这样可以有计划的避免在整个java堆进行全区域的垃圾收集。具体来说,G1收集器会跟踪各个region里的垃圾价值大小,价值就是回收所获得的空间大小及回收所需的时间经验值,然后在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间,优先回收价值收益最大的那些region。
优势:
(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停顿时间制定回收计划。
九:垃圾收集器参数介绍
note:注意在讨论垃圾收集器的上下文语境中
并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍处于等待状态。
并发(Concurrent):指用户线程与垃圾收集线程同时执行(不一定是并行,可能是交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。