垃圾回收算法详解(一)基础算法

一、算法图谱

这里写图片描述

二、算法介绍

2.1标记清除法

标记清除法分为标记阶段与清除阶段,先来看个图解。

这里写图片描述

这里写图片描述

上图描述:从根节点出发,标记所有能从根节点到达的节点。

这里写图片描述

上图描述:从堆开头开始遍历,遇到未被标记的节点就将其插入到空闲链表中,遇到已标记的节点则清除其标记。


伪代码描述如下

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

以上是垃圾标记清除阶段伪代码,总过程就是先标记,后清除。即每次触发GC时都会执行这两步操作。


如下是分配内存的伪代码,算法逻辑为:

如果刚好找到的块的size与所需size相等,则直接返回该块;
如果找到的块的size大于所需size,则将该块分割成大小为size和剩余size的两部分,将size那部分返回。

这里写图片描述



2.2引用计数法

与标记清除法不同,引用计数法并没有明确的启动GC的语句。

标记清除法会在分块不够时让mutator触发garbage_collect()函数来执行GC操作。

引用计数法则是在mutator正常处理流程中通过增减计数器的值来进行内存管理,从而达到GC的效果。


引用计数法主要涉及两个函数,new_obj()与update_ptr()函数,即开辟内存块阶段和更新引用阶段。伪代码如下:

这里写图片描述

上图:在分配阶段,如果找到合适的块,则将该块计数器加1.

这里写图片描述

上图:
update_ptr(ptr, obj)函数是将ptr指针指向obj

首先要对obj的计数器加1

然后将ptr指针之前指向的域的计数器减1

最后将ptr指向obj

注意:为什么要先执行inc_ref_cnt(obj)后执行dec_ref_cnt(*ptr)呢?
这是因为,当obj与*ptr表示同一个对象时,如果先执行dec_ref_cnt(*ptr),那么该对象的计数器值就是0,则该对象会被回收了,那么再执行inc_ref_cnt(obj)会引发BUG。

这里写图片描述

这里写图片描述

上图:dec_ref_cnt(obj)先对自己的计数器减1,然后遍历自己的子节点,将子节点的计数器减1。

reclaim(obj)函数表示将obj插入到空闲链表中。

2.3复制法

GC复制算法将内存空间分为两个相同大小的From区域与To区域,

执行GC操作的过程就是把From区域里的所有活动对象复制到To区域,

然后将原空间的所有对象回收掉,最后将From和To角色互换,新的To又变成了存放活动对象的From

好了,废话不多说,先来看一波图解

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

图解的细节可能不够,再来看一波伪代码

这里写图片描述

如上图:复制操作先将空闲链表头指向To空间的起始位置,

然后从root节点开始遍历From空间,将From空间的所有活动节点复制到To空间

最后清除From空间里所有对象,并把From空间和To空间互换

这里写图片描述

如上图:

copy(obj)函数是将处于From空间的obj复制到To空间的操作,

其中obj对象有两个标志位:
tag表示是否已经被复制,目的是防止子对象被多次复制;
forwarding表示From空间中的obj对象在To空间中的复本的位置。copy函数最后会返回该值。

copy_data($free, obj, obj.size)表示将obj复制到$free链表空间中去,大小为obj.size。

每次复制完毕,将$free指针向后移动obj.size个单位,使下一个复制的节点紧挨着放在前一个节点后面。

这里写图片描述

如上图:GC复制算法的分配操作

第一步:判断空闲区域加上size大小后,是否超过整个栈空间的一半。其中HEAP_SIZE表示From空间与To空间大小之和。

第二步:如果超过了,则执行复制操作。如果复制之后,所需的空间还是不够,则抛出异常。

第三步:在free中开辟一个所需的size大小的空间给obj,然后将$free指针向后移动size位。
最后返回obj。

2.4标记压缩法

标记压缩法:顾名思义,分为标记阶段与压缩阶段。其中标记阶段与标记清除法一样,压缩阶段是讲所有活动对象紧挨着放在一起。先来一波图解吧。

这里写图片描述

这里写图片描述

这里写图片描述

标记阶段很好理解,压缩阶段可能会有些复杂,别急,再来看一波伪代码。

这里写图片描述

如上图:标记压缩算法的压缩阶段分为三步
1.设定forwarding指针
2.更新指针
3.移动对象

这里写图片描述

这里写图片描述

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值