jvm YGC是如何识别要回收的对象?

问题

我们通常说jvm识别垃圾对象有两个方法:

  • 引用计数法
  • 可达性分析

老年代肯定是用的可达性分析,先标记GC roots,然后依据这些根对象来做遍历访问,能够访问的对象就是活的对象,其他对象就是没有引用的对象,可以回收,那么针对年轻代的垃圾回收,它是如何来标记的?

可达性分析

首先,引用计数法无法解决循环引用的问题,几乎不被采纳,可达性分析是一个比较好的方法,所以答案是YGC采用的也是可达性分析方法来做垃圾回收处理。那么YGC和FGC是都是可达性分析,也都要找GC Roots,那么2者找到的root集合都是一样的吗?如果是一样的,那么YGC也会把老年代的对象做可达性分析,这样遍历浪费的时间就太多了,毕竟年轻代的数据较小,并没有很多数据。所以垃圾回收算法是如何处理的呢?

card table

首先要了解一个概念:跨代引用,这是指老年代对象里有引用指向年轻代对象,所以年轻代没有GC Roots来做引用,可能也不能回收,因为老年代可能有,所以,为了知道对象 是否可以被回收,还需要遍历一遍老年代。那这就违背了分代回收节省时间的初衷了。那怎么办?
这就是card table里记录的东西了。不再需要通过搜索遍历old gen来获取他里面对象对young gen里对象的引用,查card table就OK了。而且YGC的时候,不会遍历老年代的对象,那么怎么识别是不是老年代呢?通常young gen与old gen都是有地址范围的,拿着指针对那地址范围查一下就好了。HotSpot VM老的GC都是要求整个GC堆在连续的地址空间上,只有一个分界线,一侧是young gen另一侧是old gen,所以检查分代的开销非常低;G1则需要遍历一个young gen region列表来获得young gen的地址范围。

总结一下:Young GC是不会找出old gen中的“无用对象”的。它连old gen的活的对象也不会关心。它只关心old gen里有没有引用指向young gen——这些引用必须作为root set的一部分,但它通常不关心这些引用是来自old gen里活的对象还是死的对象——old gen对象的死活要等做old gen GC或者full GC时才可以知道。HotSpot VM里只有CMS有old gen GC

备注:这里old gen 和 young gen 是指根对象,也是指GC roots。

在这里插入图片描述
HotSpot 使用 CardTable 记录老年代对年轻代的引用。把老年代按照 4KB 的大小分块,每一块对应在 CardTable 中都是1 bit。当值为1时,表示这4KB 的内存中有对年轻代的引用,需要加入到 GC Roots 中。

分代的好处

分代的好处 :

  • 1)减少stop the world的时间;
  • 2)提高内存分配的效率。第一点好理解,第二点不太清楚,是跟在新生代采用的复制算法有关吗,重新分配的时候直接修改指针地址即可。

参考博客

java的gc为什么要分代?
Java中的GCRoots到底有哪些?年轻代gc和老年代gc的GCRoots是如何区分的?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值