【jvm垃圾收集之跨代引用】

jvm垃圾收集之跨代引用

跨代引用

目前的垃圾收集器多数都是基于分代收集理论进行的。以Parnew+cms垃圾收集器为例,假设要进行一次新生代的垃圾收集,但新生代的对象是完全有可能被老年代中的对象引用的,为了判断新生代中某个对象是否存活,需要额外遍历整个老年代来确保可达性分析的正确性,反过来也是一样。这种方案固然可行,但同时给垃圾收集带来很大的性能负担。
注:不仅新生代、老年代存在跨代引用,G1的rigen之间也存在跨代引用,即所有涉及到部分区域收集的收集器都面临这样的问题。

记忆集和卡表

为了解决这个问题,jvm引入了记忆集和卡表,用于避免将非收集区域加到GcRoot的扫描范围。

记忆集是一种数据结构,用于记录从非收集区域指向收集区域的指针集合(摘抄于虚拟机这本书)。

解释下,假设需要对新生代进行垃圾收集,需要在新生代中维护一个数据结构,用于标记哪些老年代的内存有对新生代的引用。GCRoot扫描时,只需对含有对新生代引用的老年代部分进行扫描即可。
卡表又是什么呢?
卡表是对记忆集的一种实现(类似于 HashMap 和Map的关系)。即,记忆集是一种思想,可以通过很多实现方式实现,卡表就是其中一种实现,也是目前最常用的一种实现方式。
hotSpot虚拟机中卡表的实现方式是一个数组。

CARD_TABLE[this.address>>9]=0;
OR
CARD_TABLE[this.address>>9]=1;

数组CARD_TABLE每一个元素都对应一块固定大小的内存块,称为内存页,一个内存页的大小是2的9次幂(512字节),相当于内存位置除与512。即将连续的内存划分为大小为512字节的若干块,CARD_TABLE[0]对应第一块,CARD_TABLE[1]对应第二块,CARD_TABLE[1000]对应第1001块内存。
很明显,一个内存页可以存放很多对象,只要其中有一个对象存在跨代引用,那个数组对应的值就为1,称之为脏页。在进行垃圾收集时,只要扫表脏页部位的内存即可。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值