一文告诉你JVM的标记-清除、标记-复制、标记-整理三种垃圾收集算法

前言

无论是面试,还是平时JVM学习都遇到垃圾回收(简称GC),GC常用的垃圾收集算法有三种:

  • 标记-清除
  • 标记-复制
  • 标记-整理

当然,从算法的名称就知道,标记这个操作是必须的,剩下的就是操作核心。下面我们来看看这三者的优劣势。

GC ROOT根

在开始前我们还是要了解下一些相关概念,上面提到的算法中都有标记这个操作,其实标记代表对可回收对象进行标识

那一个对象是用什么条件来判断是否可回收?答案就是GC ROOT根。一般正常情况下,如果一个对象还在其它类或方法引用的话,那么该对象的引用链是能够到达GC ROOT根的,否则当一个对象不能够到达GC ROOT根的话,就代表该对象已经没有其它被引用的地方,在下次GC的时候就会被清掉。
在这里插入图片描述

标记-清除算法

现在我们来聊下标记-清除算法,同样的该算法包含两个阶段:标记阶段和清除阶段。
标记阶段就是从GC ROOT根开始遍历,标记所有被引用的对象。
清除阶段就是对堆内存从头遍历,如果发现有对象没有被标记,则清除。
当然这么说有点抽象,下面我们来看张图片:
在这里插入图片描述
上图是一块内存空间,可以看到,绿色的是保留对象,黄色的是可回收对象,说明现在已经完成了标记阶段,下面我们来看下一张图:
在这里插入图片描述
可以看到回收后会产生大量的内存碎片,如果想分配较大内存给较大的对象,但因为很多内存地址不是连续的而引起内存不足的情况,那可能又会发送GC了。

所以标记-清除算法的优缺点很明显,快速回收对象,不用移动对象成为了速度上的优势,但又因为优势的原因产生了过多的内存碎片。

标记-复制算法

下面我们来看看标记-复制算法,和标记-清除算法最大的不同就是将原本的内存空间一分为二,至于有什么用途,待我一一道来。

标记阶段就是各位看官可以复习下标记-清除算法的标记阶段。
复制阶段,上面提到过将内存一分为二(这里称为A区域和B区域,A和B区域大小相等),当A区域内存不够了,就会把A区域中标记为保留对象的对象复制到B区域,然后A区域的对象全部清理,同理,B区域不够内存的时候就会发生同样的操作。

下面来看看图:
在这里插入图片描述
在这里插入图片描述
标记-复制算法已经解决了回收后出现内存碎片的问题,但是一共有两大弊端:

  1. 内存空间变小,后果是内存回收的次数变得频繁。
  2. 如果有太多的保留对象,那么复制阶段的工作量变得庞大。

标记-整理算法

最后一个要介绍的是标记-整理算法,它能够解决复制算法的弊端和清除算法的弊端,那它是怎么做到的?
标记阶段做的和清除算法一样,没什么不同。
整理阶段和清除算法的清除阶段差不多,但是最大的不同的就是会重新编排各个对象的内存地址。

看图:
在这里插入图片描述
在这里插入图片描述
可以看到保留内存大小的同时,也不会出现内存碎片,是不是很完美?但是什么事都有两面性,移动对象的工作并不是那么简单,首先修改内存地址,修改内存地址后引用该对象的对象也要修改,所以整体上这也是一个非常比较庞大的工程。

结论

虽然各有各的缺点,但是现在的HotSpot虚拟机里面的收集器(例如G1、GMS)很多都是搭配使用不同算法,这样来达到一种取长补短的效果。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值