垃圾回收算法详解(一)基础算法
2017-04-04 20:51
232 查看
一算法图谱
二算法介绍
1标记清除法
2引用计数法
3复制法
4标记压缩法
上图描述:从根节点出发,标记所有能从根节点到达的节点。
上图描述:从堆开头开始遍历,遇到未被标记的节点就将其插入到空闲链表中,遇到已标记的节点则清除其标记。
伪代码描述如下
以上是垃圾标记清除阶段伪代码,总过程就是先标记,后清除。即每次触发GC时都会执行这两步操作。
如下是分配内存的伪代码,算法逻辑为:
如果刚好找到的块的size与所需size相等,则直接返回该块;
如果找到的块的size大于所需size,则将该块分割成大小为size和剩余size的两部分,将size那部分返回。
标记清除法会在分块不够时让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插入到空闲链表中。
执行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。
标记阶段很好理解,压缩阶段可能会有些复杂,别急,再来看一波伪代码。
如上图:标记压缩算法的压缩阶段分为三步
1.设定forwarding指针
2.更新指针
3.移动对象
二算法介绍
1标记清除法
2引用计数法
3复制法
4标记压缩法
一、算法图谱
二、算法介绍
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.移动对象
相关文章推荐
- Java Garbage Collection基础详解------Java 垃圾回收机制技术详解
- JAVA基础--垃圾回收机制及算法
- Java垃圾回收之复制算法详解
- Java Garbage Collection基础详解------Java 垃圾回收机制技术详解
- java基础—JVM的垃圾算法有哪几种?CMS垃圾回收的基本流程?
- Java垃圾回收之复制算法详解
- JVM垃圾回收算法及回收器详解
- JVM垃圾分代回收算法详解
- JVM垃圾回收算法及回收器详解
- Java虚拟机垃圾回收(一) 基础:回收哪些内存/对象 引用计数算法 可达性分析算法 finalize()方法 HotSpot实现分析
- Java垃圾回收之标记压缩算法详解
- JVM基础研究整理之基本垃圾回收算法
- jvm基础知识三-----基本垃圾回收算法
- Java基础:JVM垃圾回收算法
- Java垃圾回收之标记清除算法详解
- JVM入门,java环境基础+理解内存+垃圾判定、回收算法
- JVM垃圾回收机制和算法详解
- JAVA基础--垃圾回收机制及算法
- Java Garbage Collection基础详解------Java 垃圾回收机制技术详解