JVM-CMS全过程分析

其实网上有很多这类的文章,但是主要最近闲来无事,就写一下自己在经过了各类书籍的研究后得出的一些自己的见解。

那么CMS的大部分流程其实都有说到,那么我们就从每个细节开始讲解一下吧。

1.初始标记
2.并发标记
3.重新标记
4.并发清除

一.首先是第一步:初始标记,该过程会导致STW,这个过程是为了扫描JVM当中的根对象(GC roots)以及直接关联的对象,所谓的根对象一般来说的话通常是指(1)栈中所使用到的对象。(2)本地方法所使用到的对象。(例如native)。(3)Class对象。(4)静态+final变量。(5)老年代对象(并不是说所有老年代对象,是指card table中的老年代对象,也就是指那些有年轻代引用的老年代对象,这是种以空间换时间的方法,分代GC年轻代时,不用扫描老年代,节约时间)。等等(可以参考的文章)https://blog.csdn.net/xhh198781/article/details/42213847

那么这个时候扫描的时候就有两种方式,(1)广度优先(2)深度优先。那么CMS选择的是深度优先,这样的好处比较明显,因为计算机有一个预读机制,那么这个时候深度优先就会比广度优先更有效率。那么找到之后需要如何标记喃?

这个时候就会出现一种标记方法,三色标记法(黑白灰)。刚开始扫描一个对象的时候会先把它标记为灰色,然后去遍历其引用

(1)没有引用了,那么会把他变为黑色。

(2)遍历其引用,首先将他变为黑色,然后将该引用变为灰色,接着遍历引用。

那么JVM是如何处理颜色喃?

(1)黑:遍历完毕,不是垃圾

(2)灰:正在遍历

(3)白:垃圾

那么初始标记只会有两种颜色,黑色和灰色。那么这个时候第一步就走完了。

二.并发标记。

就是并发标记第一步标记的对象,把目前存活的对象标记上黑色。

由于叫做并发标记,那么何谓并发?

就是指GC线程和用户线程一起运行。那么中间就有可能出现对象关系发生改变的情况了。那么我们举个例子

下图最开始的关系是 A -> B -> C(A拥有B的引用,B拥有C的引用)。

JVM-CMS全过程分析_第1张图片

那么在第二步刚好扫描到B的时候,用户线程将关系变成了A ->C ,B变成无引用。

那么这个时候C就可能在系统中找不到了,因为A已经是黑色了,不会再根据A去搜索了。

所以这个时候CMS提供了一种write barrier。

write barrier是指记录当时引用的变化情况。

当整个环境中不存在灰色的时候就是重新标记的时候了。

三.重新标记

所谓的重新标记是指将write barrier中的关系变化修改到并发标记的三色标记当中,例如上图,这个时候首先会进行STW,然后将C标记为灰色,继续遍历即可。完成之后会进行下一步并发清除。

四.并发清除

并发清除是GC线程和用户线程一起执行的,那么这个时候新生成的对象是不会在这次GC范围之中的,那么就会有浮动垃圾。

那么只会处理在这次GC中被标记(为白色)的了。并且一旦经过了重新标记之后,仍然是白色的对象就不会被引用了。

如果只是标记清除即可,如果发生整理,和将年轻代移动到老年代的时候,就需要涉及到修改指针的问题了,

那么流程大概是将该对象进行复制,并将其移动,在原来的位置处,记录一个forward地址,该forward地址是移动后的位置,然后找到引用该对象的老年代以及当前一级引用对象,修改其引用地址即可,如果后续有对象引用该对象,那么直接将后续对象的引用地址修改即可。

你可能感兴趣的:(JVM)