老年代的垃圾回收算法

之前看过了垃圾回收算法的新生代GC,也是使用的一种比较浪费内存的复制算法,晚上看书又接着往下看了一点,

堆 = 新生代+老年代,但是要注意一点老年代不包括永久代(方法区),也就是说堆内存中只有新生代和老年代,而永久代是指的方法区。

之前介绍过新生代中的垃圾回收机制了,再来介绍一下老年代的垃圾回收机制里面使用到的算法。

新生代GC:MinorGC
之前介绍过了不说了,复制算法图解也比较清晰

老年代GC:FullGC
我们先说FullGC出现的原因吧,FullGC是老年代的GC,在新生代如果说存在的对象或者说新创建 出来的对象由于某些原因需要移动到老年代中,但是老年代中压根就没有这么大的内存空间去容纳这个对象, 那么就会引发一次FullGC,如果在执行完FullGC之后,还是没有办法给这些对象分配内存,那么凉了,该抛出异常了,异常类型就是OutOfMemoryError。

而FullGC使用的是和MinorGC不一样的算法,它使用的是标记清除算法,听名字,挺好理解的,来波图示解析一波。
深入了解JVM一书中的图示是这个样子的,

看名字的话是先标记,然后在删除。这也是也给最最基本的算法。
这个算法就是分两个步骤

  1. 标记(Mark)过程:找到所有的可以访问的对象,做个指定的标记。
  2. 清除(Swep)过程:遍历堆内存,把未标记的对象进行一个回收。

之前看一些文档上说,先标记,然后把没有标记的对象给回收掉,其实意思都差不多,但是在深入理解JVM一书中说到,首先标记出所有的需要回收的对象,在标记完成之后统一回收所有的被标记的对象, 其实我的理解和书中感觉有点不太一样,不过区别也不大。我说说我的理解吧。

在了解了这个之后,我们还得说一个概念,那就是GC Root,Root我们可以理解成一个根节点

就像这个样子

上图中的a,b,c,d,就是活着的对象,如果说存在这引用,比如说b引用的a,那么a他就是属于活着的对象。
当我们老年代内存区中的有效的内存空间不够的时候,那么这时候整个世界都要安静下来了(stop the world),这时候就要开始准备进行垃圾回收了。

  • 标记:遍历所有的GC Roots,然后将所有GC Roots可达的对象标记为存活的对象。就是我们图中所标记的a,b,c,d.
  • 清除:清除的过程将遍历堆中所有的对象,将没有标记的对象全部清除掉。
    也就是说,如果内存不够,GC线程就会被触发然后将程序暂停,随后将依旧存活的对象标记一遍,最后再将堆中所有没被标记的对象全部清除掉,接下来便让程序继续恢复运行。
    流程图就想这个样子的
    初始下的老年代中的对象状态

这时候都是没有被标记的状态,接下来内存不够,GC线程停止,开始进行标记了

按照根节点开始遍历
标记的abcdeh都是存活的对象,接下来开始标记。


接下来就是清除数据了,这个就更加的简单了


清楚完成之后还有就是把标记去除掉,可以下次进行标记清除的时候继续清除


这样标记清除就执行完毕了,剩下还有两个要说的地方,
一是在进行标记清楚算法的时候为什么要让程序停止,(stop the world)。
二是标记清除算法的优点和缺点又是什么?

(Stop the World)

程序停止其实可以理解,因为如果说不停止程序的话,我们在标记完成这个b对象之后,我们new出一个新的对象J,可以从B指向J,也就是说,这时候J应该是被标记的状态,但是实际情况肯定不是,这个对象在B标记完之后,马上都要结束了,我们又new出来一个对象,可想而知,他肯定是没有被标记的,所以在第二阶段进行清除的时候,这个苦命的J将会被清除掉, 那这样肯定是不符合我们的实际情况的。

你想呀这刚刚new出来的对象结果被清除了,忽然变成了空值,那就不符合我们的要求了。所以他会让程序先停止,然后不会再出现这种情况,然后进行开始标记阶段。

优缺点

首先我们可以先看缺点,他的缺点非常明显,

  • 因为他会递归遍历Root,这样的话 Stop the World的时间就比较长了,这样一直让人等待的滋味可不是那么好受。
  • 第二个就是这种清除方式清除出来的内存空间是不连续的,你看这个图

死亡的上下分成了2部分,是不连续的,这样给JVM又造成了一种额外的负担,他需要去维持一个内存的空闲列表,如果说我们在这时候去new一个数组,你想想他去找这个连续的内存空间的话,是不是就要困难很多呢?

他的优点也有,

  1. 比如说不会出现循环引用,
    我们可以想想 两个类 互相引用,A中newB,B中newA,那这样岂不是a.b=b ,b.a = a ,是吧 ,而标记清除算法在走完了之后,是可以回收a,和b的,因为他是从根元素开始遍历标记,也就是从ab开始,那么单一的a和单一的b就是没有被标记的,所以,这样就避免了循环引用的问题
    2.还有一点感觉没啥区别,都是内存不够的时候才进行的引用。这没啥说的。

标记–整理算法

而因为标记–清除算法会导致内存分配都出现了各种不均匀的空间,这时候就有了另外的一种算法,直接把那些存活的对象标记出来,然后给他怼到内存空间边界,然后剩下的直接全给他清除了。这方法图解看的一清二楚,剩下的都是和标记清除算法一样的,好像没啥解释的,直接上图。

书中你看就是把存活的都给怼到内存空间的上边,你也可以随便的理解成上下左右都ok。

以上就是堆内存中的老年代的两种垃圾回收算法了,如果有不合适的,希望大佬可以指正,一起讨论一下。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
jvm年代垃圾回收算法包括标记-清除算法和复制算法。标记-清除算法通过可达性分析,标记出所有需要回收的对象,然后统一回收所有被标记的对象。但这个算法效率较低,并且清除结束后会造成大量的碎片空间。有可能会在申请大块内存时由于没有足够的连续空间而需要进行再次垃圾回收。 复制算法则会将存活的对象移动到一起,然后清除边界外的垃圾对象。这个算法适用于新生代的垃圾回收,它的效率较高。在年代中,常用的垃圾回收算法是Serial和SerialOld。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [一文了解JVM全部垃圾回收器,从Serial到ZGC](https://download.csdn.net/download/weixin_38725531/15453069)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [JVM常用垃圾回收算法](https://blog.csdn.net/qq_36818328/article/details/128412384)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [JVM垃圾回收算法](https://blog.csdn.net/weixin_44130094/article/details/123504630)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丶懿

你的鼓励是我最大的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值