垃圾回收-标记整理算法的两种实现
导语
传统gc算法有:标记清除,复制算法,标记整理等。它们各有优点,标记整理的优点就是空间整理功能。本文主要介绍标记整理算法的两种实现方式。
前言
- 活动对象:可以存活的对象
- 非活动对象:可以被回收的对象
- 算法以伪代码表示
Lisp2 算法
Lisp算法包括两个阶段
- 标记
- 压缩
-
标记阶段:选取gc根对象。从这些对象开始向下遍历其子对象,最终可能会形成一个又向有环图。在此图中的对象就是活动对象,也就是将要压缩的对象。
-
整理阶段:将对象向着一端移动,移动后对象的相对顺序不变,但是对象紧临。
比如:在垃圾回收前:有ABCDEF五个对象,可以看出A和E是非活动对象。其中根引用了B和D,B引用了C,D引用了F
标记结束后:
在垃圾回收后:
标记阶段算法
选取gc roots,然后以深度优先或者广度优先的方式遍历。
mark_phase(){
for(r : $roots)
mark(*r)
}
mark(obj){
if(obj.mark == FALSE)
obj.mark = TRUE
for(child : children(obj))
mark(*child)
}
$roots
为gc roots,mark
是对象头的标记位
标记的时候可以在对象头上标记,但是这样与写时复制不兼容。当复制了一个对象,还不需要写的时候开始gc,那么就必须进行对象复制操作。为了解决这个问题可以使用位图表示,不再操作对象头,这样与写时复制兼容,并且标记与清除效率更高。
这种朴素的标记法,在标记阶段必须全局暂停,为了可以并发,可以使用三色标记法。
压缩阶段具体实现
lisp2中的对象中的对象:在对象头中有一个forwarding指针,指向将来该对象的位置。
步骤:
compa