上篇文章说了CMS垃圾收集器使用以及三色标记如何解决cms的一些问题。分别有初始标记,并发标记,重新标记,并发清理,并发重置。
一、G1收集器(Garbage-First)
-XX:+UseG1GC
这是一款面向服务器的垃圾收集器,主要针对设备多核cpu和大内存的机器。以极高效率满足GC停顿时间要求,还具备高吞吐性能特征。
Region
G1让我们忘记以前的年轻代老年代,但只是物理和以前不同,但是他会分为多个大小相等的小块(Region),jvm最多可以有2048个region。
每个小块分别代表E(eden)、S(survivor)、O(old)、H(humongous)。
一般默认就是划分2048个region,比如堆内存是4096M,则Region是堆的大小除以2048,每个region的大小是2M。推荐默认方式。
(也可以用-XX:G1HeapRegionSize= 来修改他的大小)
所以老年代和年轻代已经在物理上不是连续的,而是分为不同的region集合。
默认年轻代占比百分5,如果堆大小是4096,每个region是2M,那么对应大概100个Region。
可以通过-XX:G1NewSizePercent设置新生代初始占比。
在系统运行的时候也会慢慢给年轻代增加占比,但最大不会超过百分之60。
最大值也可以设置-XX:G1MaxNewSizePercent调整
比例还如之前的比例8:1:1,比如现在100个region,eden则是80个,s0和s1分别是10。
动态变化:一个region之前是老年代,但是做完GC之后可能变成年轻代,说明region区域功能可能动态变化。
G1垃圾收集和前面都是一样的,唯一不同的就是对大对象的处理,G1有专门分配大对象region的区域叫humongous区,而不是让大对象进入老年代中,节约老年代空间,正常大于region百分之50的对象就属于大对象,直接进入humongous,当对象太大的时候,会跨多个humongous存储。fullGC的时候会将humongous一起回收。
(前面说了一个region是2M,也就是大于1M的时候直接进入humongous)
二、G1收集器步奏
1、初始标记:STW暂停其他线程,记录GC roots直接引用的对象,速度很快。
2、并发标记(Concurrent Marking):用户线程和GC线程一起运行标记,与CMS的并发标记类似。
3、最终标记:STW暂停其他线程,整理一些刚刚标记的对象,与CMS重复标记类似。
4、筛选回收(Clearup,STW):
5、筛选标记:筛选是对各个region的回收价值和成本进行排序,根据用户所期望的GC停顿进行STW时间来制定回收计划(-XX:MaxGCPauseMillis),如果1000个region满了,这时候默认是200ms,只能回收800个region,这800个region就是Collection set,尽量把gc回收控制在我们指定时间内。这个阶段也可以与用户线程并行,但因为只回收一部分,并且时间可控,所以STW效率可以更高。他是采用复制算法来垃圾回收,所以几乎不会产生碎片。内部使用复制算法,但是从整体来看,像是标记整理算法。
(注意:CMS回收阶段是用户线程一起并发,G1内部太复杂,并没有并发回收,不过到了ZGC,Shenandoah就实现并发收集,Shenandoah可以看做并发升级版本)