一)ZGC介绍:ZGC停顿时间不超过了1ms,且不会随着堆的增加而增加
如果堆空间越来越大,那么垃圾回收的造成的STW的时间会呈现线性的增长
堆空间分页模型:小页面优先回收,大页面尽量不回收
ZGC本身只是支持三种页面,分别是小页面,中页面,大页面,其中小页面指的是2MB的内存空间,中页面指的是32MB的内存空间,大页面指的是操作系统分配的大页
当对象大小小于等于256KB时,对象分配在小页面,当对象大小在256KB和4M之间,对象分配在中页面,当对象大于4M,对象分配在大页面,ZGC对于不同页面回收的策略也不同。简单地说,小页面优先回收;中页面和大页面则尽量不回收;
1)ZGC会自动识别NUMA架构,把一块大的内存拆分成若干个小内存来提供个不同的CPU来进行使用,每一块内存会让一个CPU优先访问;
2)ZGC小页面优先回收,大页面尽量不回收,可以选取垃圾特别多的页面进行回收,一个页面垃圾越多,那么回收的优先级就越高,如果将所有的页面都进行回收,那么回收的效率就特别低;
ZGC中的转移:如果是同一个页面等同于标记整理算法,如果是不同的页面,等同于复制算法
标记:从根集合出发,标记活跃对象,此时内存存在着活跃对象和死亡对象
转移:把活跃对象转移复制到新的内存上面,原来的内存空间可以回收
重定位:因为对象的内存地址发生了变化,所以所有的指向对象的老地址的指针都要调整到对象的新的地址上面
三色标记漏标:就是用来修复并发标记中的漏标记问题,就是将B扫描完成之后,B就会变成黑色,此时B引用着D,D引用着E,此时如果在并发标记过程中D指向E的指针没了(D还没有来得及指向E),此时B指向了E,此时因为B已经变成了黑色,B不会重新扫描,但是此时的E就变成了一个垃圾对象,此时就发生了漏标操作CMS使用的是增量更新G1使用的是原始快照
B C D此时扫描完成,变成绿色,M0标记位是1,此时假设B C D 扫描完成之后发现B对象指向了D对象,此时D被其他对象指向了,但是此时B不会被扫描了,此时就出现漏标的情况,此时D就是蓝色的对象就被认为是垃圾,并发标记完成变成绿色;
二)指针着色技术:
1)颜色指针是ZGC的核心概念,因为zgc在指针中借了几位来搞事情,所以它必须要求在64位的系统上,2^10=1K,2^20=1G,2^32=4G,64位系统可以达到4TB;
2)在ZGC中使用低42位来表示使用中的堆空间(真实内存),ZGC借助高几位来做GC相关的事情,快速实现垃圾回收中的并发标记,转移和重定位等等;
3)这几个标记位具有互斥性,这几个标志位有且只有一个位置为1,某一个标志位为1表示有颜色;
4)ZGC只是支持64位系统,64位指针,ZGC中低42位表示的是堆空间的地址范围,因为42位是4个T,ZGC借助高几位来实现做GC垃圾回收相关的事情,用于快速实现垃圾回收中的并发标记,转移和重定位等,这几个高位是存在互斥性的,这几个位置有且只能有一个位置置为1,只要这个位置是1,那么指针就会带有颜色,颜色指针表示的是某一个比特位是1了,那么就代表着这个指针带有颜色了,在进行垃圾回收的时候,和对象头就没有关系了,其他的垃圾回收器在进行垃圾标识的时候会把垃圾的状态写到对象头里面,但是在ZGC里面它使用的不是对象头而是指针的着色技术;
颜色指针的概念:CMS和以前的垃圾回收器是标记在对象内部的,但是ZGC是标记在指向对象的引用上面,内部会分配4个比特位专门去做标记,这就叫做颜色指针,下面是初始状态,GC垃圾回收器还没有启动:
1)初始情况下,A,B,C,D在堆上面的不同地址中,为了方便演示,对象地址就使用1-9来表示,况且都被GCROOTS引用给关联着
2)G1垃圾回收器没有启动的时候如果new 对象,那么指针的颜色就是蓝色,也就是Remapped他的标记位就是1,这个对象已经完成重定位,当指针内存地址指向真正的对象的内存地址,那么此时Remapped标记为就是1,就是刚刚new出来的对象或者是垃圾回收器已经转移完成的对象(已经完成重定位);
三)ZGC的垃圾回收过程:
1)初始标记:只是进行标记GCroots直接关联的对象,此时A的颜色是绿色,M0为1表示颜色是绿色,代表已经标记过的对象,代表这本次垃圾回收对象的指针标记过的颜色,因为此时GCROOTS直接关联的对象是A,那么ZGC就把A指针直接标记成绿色,代表A已经被标记过
初始标记存在STW,但是时间很短,初始标记就是只是需要扫描所有的GCROOTS直接关联的对象;
2)并发标记:这个过程扫描引用链上面的所有对象,这段时间GC的处理时间非常长,但是没有STW,业务线程可以继续进行执行,但是会产生漏标问题;
3)重新标记:此时需要使用原始快照来解决漏标方案,会产生STW,比初始标记快,比并发标记慢一些,经过重新标记以后,整个堆内存中蓝色的对象就是垃圾对象,如果此时有新来的new对象就会被标记成蓝色;
4)并发转移准备:在内部会使用一些算法,计算一下有哪些大概有哪些regin要进行清理和G1里面计算回收比例是一样的,那一块回收比例大一些就会回收哪一块,没有STW
4.1)进行分析,哪些页面有垃圾,哪些页面的垃圾有多少,占多少总页面比例,并进行分析,并针对于垃圾较多的区域优先进行回收,作为一个优先级别;
4.2)如果发现一个区域地方全是垃圾,然后可以在并发转移准备并发全部进行清理,对业务程序没有任何影响,这个阶段用户线程和垃圾回收线程一起跑;
5)初始转移:对应着初始标记的对象将GCROOTS直接关联的对象进行复制算法转移到另一个位置,初始转移的对象都是绿色的对象,将A的引用指针进行更新,并且将MO状态转换到Remapped状态,这个过程会造成STW,存在短暂的STW;
5.1)先对页面作短暂的STW,将GCROOTS直接关联的对象(地址1)A转移到小页面中的内存地址是10的地方;
5.2)跟新指向A对象的指针;
5.3)将指向A对象的指针变成蓝色(已经从初始阶段完成了并发转移),改之前是绿色的(代表完成了初始标记但是还没有完全完成并发转移),下面是初始转移完成的情况: