概念
浮动垃圾是指在并发标记阶段,因为采用了快照技术,可能导致在标记过程中产生新的垃圾对象,但是未被标记为垃圾,只能在下一轮回收中进行处理;写屏障技术可以保证标记的准确性,同时,在重新标记阶段STW也能保证;
写屏障是一种在对象引用关系发生变化时触发的一种机制,它会在引用关系建立后的代码中插入一段指令。这些指令负责更新卡表的状态,确保卡表能够实时反映对象之间的跨代引用关系。
-
卡表(Card Table):G1垃圾回收器中的卡表(Card Table)本质上是一个字节数组,用于记录整个堆空间中对象的引用关系。卡表将堆内存划分成多个大小为512字节的连续内存区域,称为卡页(Card Page)。每个卡页对应卡表中的一个字节,用于记录该卡页的引用状态。当某个卡页中的对象被引用时,卡表中对应位置的字节会被标记为“脏卡”
-
记忆集(Remembered Set):记忆集用于记录从老年代到年轻代的引用关系,帮助垃圾回收器在年轻代回收时快速识别哪些对象可能被老年代引用,从而避免扫描整个老年代的内存,提高垃圾回收的效率
写屏障的作用
-
维护卡表的准确性:当老年代对象引用指向年轻代对象时,写屏障会捕获并记录下来,这样在年轻代回收时,就不用扫描整个老年代找根了。
-
支持增量更新:写屏障记录了引用关系的变化,使得垃圾回收器可以在并发标记阶段根据这些变化进行增量更新,从而减少标记阶段的开销。
-
减少标记阶段的开销:通过写屏障记录引用变化,垃圾回收器在标记阶段可以只处理那些发生了引用变化的对象,而不需要扫描整个堆。
写屏障的实现方式
G1垃圾回收器使用两种类型的写屏障:
-
写前屏障(Pre-write Barrier):在引用对象赋值前进行特殊处理,主要用于记录原始的引用关系。
-
写后屏障(Post-write Barrier):在引用对象赋值后进行特殊处理,主要用于更新卡表的状态。
特别注意
在G1垃圾回收器中,写屏障技术不记录同代引用的情况。这是因为同代引用不需要额外的记录机制来处理,原因如下:
-
垃圾回收的范围:G1垃圾回收器在进行垃圾回收时,会扫描整个代(新生代或老年代)。因此,同一代内的引用不需要额外记录,因为垃圾回收器会自然地扫描到这些引用。
-
写屏障的目的:写屏障的主要目的是记录跨代引用,以确保在垃圾回收时能够正确地找到所有存活对象。对于同代引用,垃圾回收器在回收该代时会直接扫描所有对象,因此不需要额外的记录。
-
性能优化:记录同代引用会增加不必要的性能开销。通过只记录跨代引用,G1能够减少写屏障的触发次数,从而提高程序的运行效率。
总结来说,G1垃圾回收器的写屏障技术专注于记录跨代引用,以确保垃圾回收的正确性和效率,而同代引用则不需要这种记录机制。