本文主要研究一下ShenandoahGC的Brooks Pointershtml
Shenandoah面向low-pause-time的垃圾收集器,它的GC cycle主要有bash
包括Init Mark(Pause)、Concurrent Mark、Final Mark(Pause)
这个阶段用到了Brooks Pointers(
object version change with additional atomically changed indirection)进行copy
)包括Init update Refs(Pause)、Concurrent update Refs、Final update Refs(Pause)
其中Final Mark或者Final update Refs以后均可能进行Concurrent cleanup,进行垃圾回收,reclaims regionless
G1 GC在evacuation阶段是parallel的,但不是concurrent,ShenandoahGC为了作到concurrent copy使用了Brooks Pointers。wordpress
Rodney A. Brooks在<>这篇论文提出了一种使用forwarding pointer来作到concurrent copy的方案,该方案在全部对象的内存结构上新增一个forwarding pointer,它要么指向对象本身,要么指向在to-region的本身的拷贝ui
其要点以下:atom
若是在evacuation期间,其余线程经过旧的引用访问到了from-region的旧对象,它就须要根据旧对象的forwarding pointer找到to-region的拷贝对象;等全部旧对象的引用都更新完以后,后续就能够回收from-region的旧对象spa
class VersionUpdater<T, V> {
final AtomicReference<T> ref = ...;
void writeValue(V value) {
do {
T oldObj = ref.get();
T newObj = copy(oldObj);
newObj.set(value);
} while (!ref.compareAndSet(oldObj, newObj));
}
}
复制代码
这里使用do while循环,即先拷贝再进行CAS,若是CAS不成功则继续尝试拷贝和CAS.net
stub Write(val, obj, offset) {
if (evac-in-progress && // in evacuation phase
in-collection-set(obj) && // target is in from-space
fwd-ptrs-to-self(obj)) { // no copy yet
val copy = copy(obj);
*(copy + offset) = val; // actual write
if (CAS(fwd-ptr-addr(obj), obj, copy)) {
return; // success!
}
}
obj = fwd-ptr(obj); // write to actual copy
*(obj + offset) = val; // actual write
}
复制代码
在evacuation阶段,对from-region的对象的写操做会触发该对象的evacuation操做(
若是该对象在to-region尚未copy的话
)线程
stub evacuate(obj) {
if (in-collection-set(obj) && // target is in from-space
fwd-ptrs-to-self(obj)) { // no copy yet
copy = copy(obj);
CAS(fwd-ptr-addr(obj), obj, copy);
}
}
复制代码
evacuate先判断该对象是否在from-region且在to-region尚未copy,若是知足条件则进行拷贝,而后CAS修改旧对象的forwarding pointer指向拷贝对象code
object version change with additional atomically changed indirection
)进行copy,以实现concurrent copy