HotSpot算法细节实现——安全点

OopMap

垃圾回收时,如何找到垃圾?

在可达性分析算法中从GC Roots集合找引用链分析对象是否可达。

固定可作为GC Roots的节点主要在全局性的引用(例如常量或类静态属性)与执行上下文(例如栈帧中的本地变量表),Java应用越做越庞大,光是方法区的大小就常有数百上千兆,里面的类、常量等更是恒河沙数,若要逐个检查以这里为起源的引用肯定得消耗不少时间。

迄今为止,所有收集器在根节点枚举这一步骤时都是必须暂停用户线程,因此根节点枚举也会面临相似的"Stop The World"的困扰。

根节点枚举必须在一个能保障一致性的快照中才得以进行 ------"一致性":整个枚举期间执行子系统看起来就像被冻结在某个时间点上,不会出现分析过程中,根节点集合的对象引用关系还在不断变化的情况,是导致垃圾收集过程必须停顿所有用户线程的其中一个重要原因

实际上虚拟机应当是有办法直接得到哪些地方存放着对象引用的,HotSpot的解决方案中,是使用一组称为OopMap的数据结构来达到这个目的。(一旦类加载动作完成的时候,HotSpot就会把对象内什么偏移量上是什么类型的数据计算出来,在即时编译过程中,也会在特定的位置记录下栈里和寄存器里哪些位置是引用。)

安全点

在OopMap的协助下,HotSpot可以快速准确地完成GC Roots枚举,但没有为每条指令都生成OopMap。

"特定的位置"记录了这些信息,这些位置被称为安全点(Safepoint)

安全点是以 "是否具有让程序长时间执行的特征"为原则进行选定 的,所以方法调用、循环跳转、异常跳转这些位置都可能会设置有安全点

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

垃圾收集刚开始的时候需要先获取所有根节点(根节点枚举),而根节点的获取依赖所有线程抵达安全点。

可数循环&不可数循环

HotSpot虚拟机为了避免安全点过多带来过重的负担,对循环还有一项优化措施 ,认为循环次数较少的话,执行时间应该也不会太长,所以使用int类型或范围更小的数据类型作为索引值的循环默认是不会被放置安全点。这种循环被称为可数循环(CountedLoop)

使用long或者范围更大的数据类型作为索引值的循环就被称为不可数循环(Uncounted Loop),将会被放置安全点

可数循环不会被放置到安全点,不可数循环会被放置到安全点

通常情况下这个优化措施是可行的,但循环执行的时间不单单是由其次数决定,如果循环体单次执行就特别慢,那即使是可数循环也可能会耗费很多的时间。

如果由可数循环耗时时间较长,安全点导致长时间停顿,可以将循环索引的数据类型从int改为long即可

现象:

当垃圾收集发生时,如果有线程刚好执行到可数循环(较耗时)时,则必须等待循环全部跑完才能进入安全点,此时其他线程也必须一起等着,所以从现象上看就是长时间的停顿。

出现可数循环比较耗时,可以将循环索引的数据类型从int改为long。 将可数循环变为不可数循环,放置到安全点位置即可。

相关推荐
人机与认知实验室1 小时前
香港火灾与人机环境系统安全
安全·系统安全
小白程序员成长日记1 小时前
2025.11.29 力扣每日一题
数据结构·算法·leetcode
在黎明的反思2 小时前
进程通信之消息队列(IPC)
算法
老鱼说AI2 小时前
算法基础教学第一步:数据结构
数据结构·python·算法
Jing_Rainbow3 小时前
【LeetCode Hot100 刷题日记(19/100)】54. 螺旋矩阵 —— 数组、矩阵、模拟、双指针、层序遍历🌀
算法·面试·程序员
Mr.wangh3 小时前
JVM详解
jvm
地平线开发者4 小时前
征程 6 | linear 高精度输出配置方式
算法·自动驾驶
麦聪聊数据4 小时前
IT 的“控”与业务的“放”:构建基于 Web 原生架构的安全数据共享平台
数据库·sql·安全
小尧嵌入式4 小时前
C++基础语法总结
开发语言·c++·stm32·单片机·嵌入式硬件·算法
white-persist4 小时前
【攻防世界】reverse | IgniteMe 详细题解 WP
c语言·汇编·数据结构·c++·python·算法·网络安全