1. JVM G1 位图(bitmap)与卡表(cardTable)


1.1. 位图的用处

位图是把一个字节里面8位,0\1用来标识某个内存区域是否使用。

例如有两个分区,分区1中有对象student,分区2中有对象score,并且student.score = score。如果要找到分区1是怎么引用的分区2,应该怎么做?

  1. 对1分区的内存一点点的遍历。遍历的时候,判断里面的值是不是指向B分区,这种方式效率很低。

  2. 优化后的遍历,借助对象长度来遍历,根据当前遍历的对象的长度,一个一个对象去遍历。例如student长度为512K,在遍历判断引用关系后,继续遍历就从512K之后开始遍历;以此类推,一个个对象判断。

上面两种方式虽然经过了优化,但是遍历操作 在内存越大或者region越大时效率会越低。为了找一个引用关系,就要遍历一次。对象很多时,效率会十分低下。

  1. 借助额外的数据结构,位图。用bitmap记录A和B的内存块儿之间是否发生了引用,在bitmap里面用一个位,描述是否引用的状态。

    在A中维护一个bitmap,每一个位,记录在B分区中的一个字的区域是否存在引用关系,有引用关系bitmap的位就记为1,没有就记位0。这样可以直接通过位图确定是否引用,不用遍历整个A分区。

    g1_bitmap_card_01


1.2. 位图的不足

  1. 描述内容太少

    位图只有 0\1 标记,只能证明是否有引用关系。JVM在垃圾回收的时候不只需要是否引用信息,还需要其它描述信息。

    g1_bitmap_card_02

  2. 内存问题

    如果为了解决描述信息少的问题,通过增加描述位来解决,会导致位图占用的内存过大,得不偿失。故不能采用增加描述位的方案。

    g1_bitmap_card_03

    图中可知,用一个字节描述一个字很耗费内存。相当于把描述能力降低8倍,内存空间上升8倍。


1.3. 怎么优化位图?

JVM用一个字节来描述512字节的内存空间。即8位来描述512 * 8位的内存信息。这样,内存占用上大大缩减,2KB的位图就可以描述1MB的内存空间,同时也兼顾引用关系查找的速度,不需要遍历的方式找引用关系。在访问对象的时候,通过对象来访问位图对应的引用关系。

g1_bitmap_card_04


1.4. 卡表

卡表,就是把整个堆内存,按照512字节的粒度,拆分成一个个card,做成全局的卡表,卡表中每8个字节描述512字节内存的引用关系、使用情况等等信息。

g1_bitmap_card_05


1.5. 卡表和位图的关系

卡表是位图思想的一种实现方式,只是粒度不同。位图用每一个位描述数据的状态;卡表是按照位图的思想,用一个字节来描述512字节内存的状态、引用等相关数据。卡表是位图的增强版。


1.6. 卡表和Rset记忆集怎么结合使用?

g1_bitmap_card_06

提示:Rset中存储的就是卡表地址。

results matching ""

    No results matching ""