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。 将可数循环变为不可数循环,放置到安全点位置即可。

相关推荐
红红谈说8 分钟前
论坛帖子审核链路怎么设计?内容安全与状态机的一次复盘
安全·状态机·内容审核·敏感词·异步审核
风123456789~6 小时前
【架构专栏】第18章 安全架构设计 1/3
安全·架构·安全架构
天远API6 小时前
零信任架构实战:基于天远运营商三要素简版V即时版查询构建自动化司乘安全绑定网关
人工智能·安全·架构·自动化
海上小飞龙7 小时前
【KMP算法-下篇】同一道题:Java 库函数 2600 微秒,手写 KMP 16 微秒
java·开发语言·算法
青少儿编程课堂7 小时前
后缀自动机解析:本质不同子串与最长重复片段统计
c++·python·算法·bfs·信息学竞赛
朝朝辞暮i7 小时前
C++ 第 12 课:局部变量、作用域、变量生命周期
开发语言·c++·算法
乐迪信息9 小时前
港口船舶逆行怎么管?AI防爆摄像机搭载智能检测算法
大数据·人工智能·深度学习·算法·计算机视觉
Sirens.10 小时前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法
和裕10 小时前
全纸结构重型纸箱能否满足 1 吨以上设备出口熏蒸豁免要求?通关合规性全解析
大数据·运维·网络·人工智能·算法
tangguofeng11 小时前
不带头结点的链队操作集(不含InitFlag)(C语言版)
算法