一、CMS及其三色标记算法

1、核心

标记整个图谱的过程分为多步

多个线程相互工作,才能标记完

标记的算法,JVM虚拟机、go语言使用的都是三色标记算法

2、含义

从那个地方开始,用三种颜色替代

一开始,所有对象都是白色-表示从来没有接触过的对象

已经接触过,但未标记其孩子的对象,是灰色对象

找到了该对象以及所有的孩子,是黑色对象

三色是怎么进行标识的:

(1)颜色表10 00 01分别表示颜色

(2)实际:在对象头部的mark word拿出两位来进行标识

3、白色-灰色-黑色的过程

下次开始的时候,线程只需要从灰色开始即可

lua三色标记清除算法 jvm三色标记算法_CMS

4、发生的情形

业务线程和垃圾回收线程共同工作的时候

垃圾回收线程找,A找到,待回收,其孩子B找到,但B的孩子D还未找到

此时业务线程继续,被回收的A关联到B的孩子D,而B的引用被标记为空,B标记为黑

lua三色标记清除算法 jvm三色标记算法_lua三色标记清除算法_02

此时,D实际上有引用,但被清除了(B到D的引用删除,以为垃圾回收已经结束了)

5、如何修正

需要加屏障

JVM当发现黑色对象的引用指向白色时,进行一些操作--例如将A变成灰色,下次会继续从A开始找【CMS采取的方案】

CMS采取的方法叫:Incremental Update

6、CMS的解决方案存在的bug

并发标记,容易产生漏标

lua三色标记清除算法 jvm三色标记算法_算法_03

7、CMS怎么修正该bug--remark再标一遍

lua三色标记清除算法 jvm三色标记算法_G1_04

lua三色标记清除算法 jvm三色标记算法_CMS_05

实际上,其STW的时间仍然很长

8、调优

CMS的调优比较复杂,有几十个参数,都需要掌握

9、建议

原来是:PS PO

内存足够大(1G),可以最直接换成G1

二、G1

1、算法

仍然基于三色标记算法

但未标记的孩子,不会标记为灰色

2、解决方案:SATB Snapshot At the Begining

lua三色标记清除算法 jvm三色标记算法_jvm_06

B-D的引用消失,把引用记下来(白色指向的D)

对被引用对象D进行单独处理(看有没有黑色的引用指过来,如果有,就不将其标记为黑色)

引用指向的都是白对象,如果没有引用,就标记为黑色对象,否则就被标记为白色对象

3、存在问题

找有没有引用指向D

怎么着指向D的对象-扫描?

4、G1的分区模型-从G1开始,都是分区模型

lua三色标记清除算法 jvm三色标记算法_lua三色标记清除算法_07

分区后,意味着,当某个分区满了,只回收当前分区,没有必要回收其他分区

回收该分区时,有用的想会移动到其他游泳而位置

可以实现一边分区,其他线程一边运行

5、如何寻找指向当前对象的引用

在G1中,有一个remember set,记录着有多少对象指向当前分区

记忆集中寻找 

大概率,白色对象不会变为黑色

6、与其他垃圾回收器的比较

lua三色标记清除算法 jvm三色标记算法_G1_08

按照停顿时间STW,PS寻找2-3天

建议不要使用CMS,而是使用G1

没有一个默认的jdk版本,是CMS的方式

三、ZGC-Zero pause GC

1、概念

号称0毫秒,如果能达到,就和C/C++没有区别了

采用的方案是颜色指针:color pointer

ZGC关注的是地址本身,而不是实际存储

2、结构

lua三色标记清除算法 jvm三色标记算法_G1_09

2的42次方内存

现在是44次方,约4T

3、GC的过程

从各个区内,区内都是remapped

从根开始找

标记位标记指针的状态,初始标记为M0

有M0就是有用的,没有 M0,是remapped就是垃圾

线程访问M0时,对应对象的标记就会换成M0