java jvm什么是记忆集,卡表?

记忆集
            是一种用于记录 从非收集区域指向收集区域的指针集合的抽象数据结构 。如果我们不考虑
效率和成本的话,最简单的实现可以用非收集区域中所有含跨代引用的对象数组来实现这个数据结
            记忆集作用 :解决对象跨代引用所带来的问题,垃圾收集器在新生代中建 立了名为记忆集( Remembered Set )的数据结构,用以避免把整个老年代加进 GC Roots 扫描范围。事
实上并不只是新生代、老年代之间才有 跨代引用的问题 。所有涉及部分区域收集(
Partial GC )行为的 垃圾收集器,典型的如 G1 ZGC Shenandoah 收集器,都会面临相同的问题,因此我们有必要进一步 理清记忆集的原理和实现方式
          
            这种记录全部含跨代引用对象的实现方案,无论是空间占用还是维护成本都相当高昂。而在垃圾 收集的场景中,收集器只需要通过记忆集判断出某一块非收集区域是否存在有指向了收集区域的指针 就可以了,并不需要了解这些跨代指针的全部细节。那设计者在实现记忆集的时候,便可以选择更为 粗犷的记录粒度来节省记忆集的存储和维护成本,下面列举了一些可供选择(当然也可以选择这个范 围以外的)的记录精度:
            
          · 字长精度: 每个记录精确到一个机器字长(就是处理器的寻址位数,如常见的 32 位或 64 位,这个 精度决定了机器访问物理内存地址的指针长度),该字包含跨代指针。
        
          · 对象精度: 每个记录精确到一个对象,该对象里有字段含有跨代指针。
         
         · 卡精度: 每个记录精确到一块内存区域,该区域内有对象含有跨代指针。
         卡精度 所指的是用一种称为 卡表 Card Table)的方式去实现记忆集, 就是 记忆集的一种具体实现 ,它定义了记忆集的记录精度、与堆内存的映射关系等。 关于卡表与记忆集的关系,读者不妨按照 Java 语言中 HashMap Map 的关系来类比理解
         
          卡表最简单的形式可以只是一个字节数组 ,而 HotSpot 虚拟机确实也是这样做的。以下这行代 码是 HotSpot 默认的卡表标记逻辑
           
          
 CARD_TABLE [this address >> 9] = 0;
          字节数组 CARD_TABLE 的每一个元素都对应着其标识的内存区域中一块特定大小的内存块,这个 内存块被称作 卡页 Card Page )。一般来说,卡页大小都是以 2的N次幂 的字节数,通过上面代码可 以看出 HotSpot 中使用的卡页是 2 9 次幂,即 512 字节(地址右移 9 位,相当于用地址除以 512 )。那如 果卡表标识内存区域的起始地址是 0x0000 的话,数组 CARD_TABLE 的第 0 1 2 号元素,分别对应了 地址范围为 0x0000 0x01FF 0x0200 0x03FF 0x0400 0x05FF 的卡页内存块 ,如图 所示。

            一个卡页的内存中通常包含不止一个对象,只要卡页内有一个(或更多)对象的字段存在着跨代 指针,那就将对应卡表的数组元素的值标识为 1 ,称为这个 元素变脏 Dirty ),没有则标识为 0 。在垃圾收集发生时,只要 筛选出卡表中变脏的元素 ,就能轻易得出哪些卡页内存块中包含跨代指针,把它 们加入 GC Roots 中一并扫描
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值