JVM-GC Roots遍历对象图(增量更新和原始快照)

世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。

GC Roots枚举根对象的过程需要Stop The World,因为根对象相对来说是比较固定的,所以这个停顿时间基本可控并且可以接受,但是基于根对象遍历整个对象图的引用关系如果Stop The World时间就会比较长了,并且会随着对象的增多停顿时间也随着变长。为了解决这个问题,只有在搜索标记的时候让用户线程并发执行,用户线程并发执行,肯定会造成对象引用关系的变化,解决并发时引用关系变化,有两种方法,一种叫做增量更新,一种叫做原始快照。这两种方式的原理是什么呢,首先定义三种状态,黑、白、灰。黑色代表GC Roots可达并且所有引用都被扫描过的对象;白色代表GC Roots不可达或未扫描的对象; 灰色代表两者之间,至少有一个引用未扫描的对象。遍历对象图的过程其实就是白色->灰色->黑色过渡的过程,这个过程中一直是白色的对象是要被回收的,黑色的则是保留的。由于这个过程是动态的,在这个过程中用户线程会改变引用关系,所以会出现一些特殊情况:在扫描过后黑色的对象增加引用关系到白色对象和在扫描时灰色的对象断开到白色对象的引用关系。这样就有可能将后续可达的对象标记为垃圾对象。增量更新方式就是当黑色对象插入新的引用关系到白色对象时就记录下来,并发扫描结束后,根据这些记录以被记录的黑色对象为根重新扫描一次。原始快照是将灰色对象断开到白色对象的引用关系记录下来,扫描结束后根据记录以记录的灰色对象为根重新扫描一次。这两种方式其实也是垃圾收集器标记过程中:初始标记(GC Roots根对象枚举)- 并发标记 - 最终标记(增量更新或原始快照),最终标记的过程。通过这三种标记过程,可以准确的判断出垃圾对象。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/a13662080711/article/details/108333369
今日推荐