前言
JVM为了更好的管理内存,提高GC效率,一般都会对内存进行划分,比如经典的分代收集,G1推出的Region等。而Java中的垃圾收集基本都基于可达性分析算法,这就涉及到对象枚举遍历和标记的过程。
在做Minor GC的时候会对年轻代进行根节点枚举,但是如果年轻代中的一些对象被老年代引用着,那么在做年轻代可达性分析的时候就会遇到很大的阻碍,总不能在Minor GC的时候还去扫描老年代吧?这种跨代引用的问题抛开出现频率,它总是会存在,而且在G1这种多Region结构中更加突出(包括ZGC、Shenandoah等)。虚拟机为了避免全堆扫描,便引入了Remember Set。
解释
对于Remember Set,可以将其理解为一个抽象的数据结构,Hot Spot对它有一个叫做CardTable的"实现"。笼统的说,在HotSpot中CardTable是一个字节数组(jbyte*),数组中的每个元素称为一个card。一个内存地址可以被映射到CardTable中的一个位置上,怎么映射呢?比如有一块内存区域,现在从逻辑上将其按照固定大小进行划分,就像这样: