垃圾回收复制算法的基本思想很直观,甚至看上去浪费。将现有堆一分为二,一个用完后,将活动对象拷贝到另一半。但是这样做却有一些比较明显的优点。
先来看下具体算法。
看上去简单,其实还是有一些要注意的地方。
第一是防止重复拷贝,对象之间的引用可以很复杂,各种交叉;第二是拷贝后,新老堆中的引用关系要缕顺。
copying() { $free = $to_start for (r : $root) *r = copy(r) // 注意,这里实际是一个update,将对象替换 swap($from_start, $to_start) }
上述free是新堆的起点指针,复制回收刚开始时,free指向起点。开头描述的两个要注意的地方可以通过在老堆中的对象中引入两个字段来解决,分别是tag、forwarding,因为老堆中内存已经无用,两字段可以在对象原先的字段中重用。具体见下算法:
// 这里,传给copy的对象,一定是旧堆的copy(obj) { if obj.tag != COPIED // 重要,在老堆的对象中,标志这对象已经拷走。 copy_data($free, obj, obj.size) // 拷贝到free obj.tag = COPIED obj.forwarding = $free // 重要!obj是老堆中对象,forwarding字段指向了新堆中的同一对象!! $free += obj.size for (child :