JVM笔记-HotSpot的算法细节实现

本文详细介绍了HotSpot JVM在垃圾收集过程中的关键机制,包括根节点枚举、安全点、安全区域、记忆集与卡表、写屏障以及并发的可达性分析。根节点枚举时,所有收集器需要暂停用户线程;安全点是让程序在执行时能够快速暂停的位置,HotSpot使用OopMap提高查找引用效率。安全区域解决了线程在不执行状态时的处理。记忆集与卡表用于处理跨代引用,卡表通过卡精度记录指针集合。写屏障用于维护卡表的更新,防止并发标记时的对象消失问题。最后,文章探讨了并发可达性分析的挑战及解决方案,如增量更新和原始快照策略。
摘要由CSDN通过智能技术生成

1. 根节点枚举

1.1 暂停用户线程

迄今为止,所有收集器在根节点枚举这一步骤都是必须暂停用户线程的。即便是号称停顿时间可控、或者(几乎)不会发生停顿的 CMS、G1、ZGC 等收集器,枚举根节点时也必须要停顿。

这也是导致垃圾收集过程必须停顿所有用户线程的一个重要原因。

1.2 如何高效查找引用链

目前主流 JVM 使用的都是准确式垃圾收集,因此虚拟机有办法直接知道哪些地方存放着对象的引用。而 HotSpot 是使用一组称为 OopMap 的数据结构来实现的。

一旦类加载动作完成,HotSpot 就会把对象内什么偏移量上是什么类型的数据计算出来(在即时编译过程中,也会在「特定的位置」记录下栈和寄存器中哪些位置是引用),这样收集器在扫描时就能直接得知这些信息,不必挨个从方法区等 GC Roots 开始查找了。从而可以提高查找效率。

普通对象指针:Ordinary Object Pointer, OOP

2. 安全点

2.1 概述

前面「特定的位置」记录了引用信息,这些位置被称为安全点(Safepoint)。

用户程序执行时,并非在代码指令流的任意位置都能停下来开始垃圾收集,而是强制要求必须执行到安全点后才能暂停。

可以用高速公路上行驶的汽车做类比:高速公路上行驶的汽车(用户线程)不是在任何地方都能停下来的,只有到了服务区(安全点)才能停下。

2.2 安全点选取

安全点的选取既不能太多,也不能太少:

  • 若太少,收集器会等待过长时间;

  • 若太多,则会过分增加运行时的内存负荷。

安全点位置的选取标准:是否具有让程序长时间执行的特征。什么样的程序会长时间执行呢?

最明显的特征就是指令序列的复用,如方法调用、循环跳转、异常跳转等,只有具备这些功能的指令才会产生安全点。

2.3 如何让线程跑到最近的安全点

垃圾收集发生时,如何让所有线程(不包括 JNI 调用的线程)都跑到最近的安全点、然后停顿下来呢?有如下两种方案可以采用。

2.3.1 抢先式中断

  • 思想:无需用户线程代码配合,垃圾收集时,系统首先把所有用户线程全部中断;此时若有用户线程不在安全点,则恢复执行,直至它到达安全点再中断。

  • 这种方案现在几乎不用了。

2.3.2 主动式中断

  • 思想:垃圾收集需要中断线程时,不直接操作线程,只是设置一个标志位,各个线程执行过程中不停地主动轮询该标志位,若标志位为真,则在自己最近的安全点主动中断挂起。

  • 轮询标志的地方和安全点是重合的。

如何高效轮询呢?HotSpot 使用内存保护陷阱的方式,通过一条

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值