RSet介绍
在G1中,引入了RSet(Remember Set,记忆集)的概念,用来记录不同代际之间的引用关系,目的是为了加快垃圾回收的速度。
通常有两种方法记录引用关系,分别为point out和point in。比如a=b(a引用b),若采用point out结构,则在a的RSet中记录b的地址;若采用point in结构,则在b的RSet中记录a的地址。
G1的RSet采用的是point in结构,即谁引用了我。(Card Table采用的是point out结构)
为什么需要记录跨代的引用
JVM一般都会对内存进行分代处理,以提高内存分配和垃圾回收的效率。Minor GC只会回收年轻代,Major GC只会老年代,无论是哪一种GC都会面临跨代引用的情况,比如老年代对象引用新生代或者新生代对象引用老年代。
Minor GC在回收年轻代时,需要判断年轻代的对象是否存活,而年轻代的部分对象可能被老年代的对象引用,因此必须扫描老年代才不会发生误判年轻代的对象为垃圾;同理,在回收老年代时,也需要扫描年轻代。
那么无论是只回收新生代还是老年代,都需要扫描其他代的对象,相当于进行全堆扫描,效率很低。那么将代际之间的引用关系记录在一个单独的地方,只需要扫描这个地方即可,避免全堆扫描。
RSet带来的问题
- RSet需要额外的内存空间来存储这些引用关系,一般是JVM最大的额外开销的1%-20%之间;<