鉴于复制算法中,没有内存碎片的方式能大大提高分配效率,因此,在mark_sweep的基础上,也可以改良出mark_compact算法,使得空闲空间连续。同时又没有复制算法的无帮吃一半堆的问题。
首先是最简单的算法,叫Lisp2算法。
在标记阶段,不变,仍然是对每个活动对象打上标签。
随后,开始移动活动对象到堆的开头。因为没有两个堆,又要挪动对象放到一起,那么forwarding指针便需要在对象头中占用空间(复制算法中不用占用是因为它是非活动对象),且在移动前要做一轮forwarding指针的重指。还要做一轮子对象指针的重指。总体流程如下:
compaction_phase() { set_forwarding_ptr() adjust_ptr() move_obj() } // 设forward指针最简单set_forwarding_ptr() { scan = new_addr = $heap_start while (scan < $heap_end) if (scan.mark == TRUE) scan.forwarding = new_addr new_addr += scan.size scan += scan.size } // 调整对象的成员指针,指向成员在堆中的新地址。对于全局变量,因为它们是根的子对象,也需要重指。adjust_ptr() { for (r : $roots) r = r.forwarding scan = $heap_start while (scan < $heap_end) // 这里为什么要扫堆,而不能从根直接递归遍历?因为直接递归可能会递归到不正确的已经重指过的值。直接遍历的话不会有顺序问题。 if (scan.mark == TRUE) for (child : children(scan)) child = child.forwarding scan += scan.size } // 最后,移动对象//不列了,比较简单,只需要扫堆,把活动对象向前移,清除forwarding和mark标记即可
延伸阅读
- ssh框架 2016-09-30
- 阿里移动安全 [无线安全]玩转无线电——不安全的蓝牙锁 2017-07-26
- 消息队列NetMQ 原理分析4-Socket、Session、Option和Pipe 2024-03-26
- Selective Search for Object Recognition 论文笔记【图片目标分割】 2017-07-26
- 词向量-LRWE模型-更好地识别反义词同义词 2017-07-26
- 从栈不平衡问题 理解 calling convention 2017-07-26
- php imagemagick 处理 图片剪切、压缩、合并、插入文本、背景色透明 2017-07-26
- Swift实现JSON转Model - HandyJSON使用讲解 2017-07-26
- 阿里移动安全 Android端恶意锁屏勒索应用分析 2017-07-26
- 集合结合数据结构来看看(二) 2017-07-26