本文主要研究一下ShenandoahGC的Brooks Pointershtml
Shenandoah面向low-pause-time的垃圾收集器,它的GC cycle主要有less
包括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 region
G1 GC在evacuation阶段是parallel的,但不是concurrent,ShenandoahGC为了作到concurrent copy使用了Brooks Pointers。wordpress
Rodney A. Brooks在<<Trading Data Space for Reduced Time and Code Space in Real-Time Garbage Collection on Stock Hardware>>这篇论文提出了一种使用forwarding pointer来作到concurrent copy的方案,该方案在全部对象的内存结构上新增一个forwarding pointer,它要么指向对象本身,要么指向在to-region的本身的拷贝
其要点以下:atom
若是在evacuation期间,其余线程经过旧的引用访问到了from-region的旧对象,它就须要根据旧对象的forwarding pointer找到to-region的拷贝对象;等全部旧对象的引用都更新完以后,后续就能够回收from-region的旧对象
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
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指向拷贝对象
object version change with additional atomically changed indirection
)进行copy,以实现concurrent copy