前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HotSpot 图解年轻代回收

HotSpot 图解年轻代回收

作者头像
执生
发布2020-11-04 09:47:09
5310
发布2020-11-04 09:47:09
举报
文章被收录于专栏:立权的博客立权的博客

下图的 各个区域的 C++ 实现是 一般情况下的

1.GenCollectedHeap::process_roots

假如 3 和 9 的年龄未到阈值,被复制到了 to 区

6 和 8 的年龄到了阈值,被 promote 到了 老年代

被promote的对象会被 一条链表连接起来,也就是下图的红线

实际上,只是用对象的对象头去把对象连接起来(这里说的对象都是 C++ 层面对象的具体实现,也就是 oopDesc 的对象 在内存中占用的一段内存块)

spool Block 是一块块独立于堆区之外的内存,是JVM用于管理的内存,当对象的对象头要被用来做其他用途的时候(比如下图就是用来连接其他对象)

如果对象头里有重要的信息,比如年龄,锁信息等,就需要保存对象头,具体是保存到Spool Block中,而且是紧挨着存放,一个block用完了用下一块,老套路了。

使用 对象头做别的事情也是老套路了,比如可以把对象头设置成特定值,辨别是否被 mark,这一点在老年代的压缩回收中用到

接着是要处理脏卡表,也就是用户修改了引用的地方

假设对象 15 所在的 卡表是脏的,也就是 对象 15 本来有引用是指向 对象1,但是引用之前修改了,指向了 对象4,那么它所在内存区域的卡表就会被设置为脏的

这时候就需要把 对象4 按之前的方式,看看是否年龄到了阈值,是的话就复制到 to,否则promote到老年代

假设上面步骤得到的 存活对象的集合为 T0 (to区对象,promote到老年代的对象)

2.FastEvacuateFollowersClosure::do_void

以刚刚得到的存活对象集合 T0(to区对象,promote到老年代的对象)为起点,广度优先遍历所有可达的对象,也采取同样的方法处理他们(到达阈值就拷贝到老年代,否则到to区),其实处理之后他们就变成了新的 T0, 之后会一直以他们为起点,重复之前的动作

直到遍历到 T0 对象没有引用对象为止。

遍历停止的条件是 no_allocs_since_saved_mark, 老年代和年轻代有自己不同的实现

年轻代的判断依据是 to 区没有对象再添加进来,因为有对象添加进to 区的话,说明还有对象 因年龄不够而被加入 to 区, 这样的话又要遍历这个对象的引用

老年代的判断依据是 promotionInfo 链表为空,也就是上面的红色线连起来的链表 没有节点,也就是没有新的被 promote 到 老年代的对象

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-11-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档