JVM垃圾回收算法理解2之标记清除算法和标记压缩算法

标记清除算法

标记清除算法共分为两个阶段分别是标记和清楚,可以这么理解标记就是从根节点开始标记引用的对象,清除:就是未被标记引用对象,也就是垃圾对象可以被清理
原理:画图解释,
JVM垃圾回收算法理解2之标记清除算法和标记压缩算法_第1张图片
图中每个方框代表一个对象, 每个对象中都有一个mark 标记位, 最上面有个root是跟节点对象 ,从根节点对象开始箭头指向,代表root 对象引用了下面的对象,图中 root 对象共引用了两个对象,依次类推对象一层一层的引用,比如在这个时候jvm的内存用完,这个时候就开始gc垃圾回收,gc开始运行的时候回停止应用程序的运行并且开启gc线程,然后开始标记工作,按照跟搜索的算法如下图
JVM垃圾回收算法理解2之标记清除算法和标记压缩算法_第2张图片
图中按照根搜索的算法,所有从root 对象可达的对象就被标记为成活对象(绿色),从root节点到达不了红色的对象标记为垃圾对象(红色),虽然两个红色对象有相互引用但是没有被root引用,这个时候就完成了第一阶段的标记工作,标记之后mark由0变成1,在这个时候实际上就解决了引用计数法无法解决循环引用的问题,关于引用计数法请看另外的一遍引用计数博客
JVM垃圾回收算法理解2之标记清除算法和标记压缩算法_第3张图片
JVM垃圾回收算法理解2之标记清除算法和标记压缩算法_第4张图片
接下来开始清除垃圾对象,那么清除完以后存活下来的对象mark标记由1还原成0 如下图
JVM垃圾回收算法理解2之标记清除算法和标记压缩算法_第5张图片
清除工作完成之后就开始唤醒应用的线程,程序从新开始运行,gc会重复循环以上整个过程;
标记清除算法优缺点:

1、标记清除算法解决了引用计数法循环引用的问题,但是因为标记和清除两个动作都需要遍历所有的对象,并且在gc时要停止应用运行,对于交互性要求比较高的应用来说就不能满足
2、通过标记清除算法整理的内存碎片化比较严重,因为被清除的对象可能存在内存的每个角落,所有清理出来的内存是不连贯的如图:

JVM垃圾回收算法理解2之标记清除算法和标记压缩算法_第6张图片
整个图是个内存,绿色是存活对象,红色是即将被清除的垃圾对象,白色是空闲内存 ,当需要jvm需要申请内存时发现内存不够用这个时候会将垃圾对象清除,得到的是如下的内存模型,此刻内存空闲空间并不连续就会导致后续jvm申请内存碎片严重,是标记算法的缺点
JVM垃圾回收算法理解2之标记清除算法和标记压缩算法_第7张图片
为什么标记清除会暂停应用:因为标记和清除是遍历所有的对象,标记是根据root 引用标记,,程序在运行的时候会产生新的对象,会导致标记不准确清除对象的时候也就不准确,会出现存存活的对象也被当做垃圾回收,所以必须暂停应用标记和清除;

标记压缩算法

标记压缩算法解决了标记清除算法碎片化比较严重的问题;
标记压缩算法分为标记和标记清除算法一致,但是清除不同,在清除垃圾对象的时候并不是简单的清除垃圾对象而是讲存活的对象压缩到内存的一端,然后清理边界以外的垃圾对象,从而解决碎片化严重的问题
JVM垃圾回收算法理解2之标记清除算法和标记压缩算法_第8张图片
解决了碎片化严重的问题,但是标记压缩算法多了一步对象移动内存位置的步骤效率也就受到相应的影响

你可能感兴趣的:(JVM优化)