来聊聊JVM中安全点的概念

news2025/7/19 19:13:11

文章目录

    • 写在文章开头
    • 详解safepoint基本概念
      • 什么是安全点?为什么需要安全点
      • JVM如何让线程跑到最近的安全点
      • 线程什么时候需要进入安全点
      • JVM如何保证线程高效进入安全点
      • 如何设置安全点
      • 用一次GC解释基于安全点的STW
    • 实践-基于主线程休眠了解安全点的工作过程
      • 代码示例
      • 基于日志印证执行流程
      • 优化思路
    • 关于安全点更进一步的理解
      • 关于安全点的调优建议
      • JDK11对于安全点的优化
      • RocketMQ中对于安全点的优化
    • 小结
    • 参考

写在文章开头

近期在分享关于synchronized关键字的文章的时候提到了一个关于安全点的概念,有读者反馈这块知识点讲的有些潦草,遂以此文简单介绍一下JVM中关于安全点的概念。

在这里插入图片描述

详解safepoint基本概念

什么是安全点?为什么需要安全点

在正式讲解安全点之前,我们不妨复习一下JVM中垃圾回收的基本过程,我们以CMS垃圾回收器为例,其垃圾回收过程在完成GC Roots查找与收集之后就会按照如下步骤执行:

  1. 初始标记
  2. 并发回收
  3. 最终标记(重新标记)
  4. 并发清除

要知道固定可作为GC Roots的节点主要是:

  1. 全局引用:例如常量或者静态变量。
  2. 执行上下文即栈帧中的变量表。

对于现代java应用而言,光是方法区就可能有数百上千兆,所以对于这些起源的引用也并非一件容易的事情。这也就意味着JVM在进行垃圾回收时并不能通过逐个扫描检查来实现。
就目前主流的JVM来说,针对根节点枚举基本都是采用空间换时间的策略,也就是使用一组OopMap,全称为"Object Pointer Map"(对象指针映射),本质上就是一个位图索引,它会通过以下两个时机完成对象信息的缓存:

  1. 类加载完成后,hotSpot就会基于类的偏移量信息计算出来并缓存。
  2. JIT阶段也会在特定的时机(这一点后续会详细说明)计算出栈或寄存器中的那些位置是引用,并将其缓存。

如此一来,下次进行根枚举时就可以直接基于OopMap高效完成:

在这里插入图片描述

但是java进程的运行的瞬息万变的,可能此刻的对象在下一刻就不可用,下一刻又有新的对象诞生,这种引用关系的实时变化亦或者说导致OopMap内容变化的指令是非常多的,若针对每一个指令都设置对应的oopMap,那么内存的开销是非常高昂的。

所以就有了安全点(safepoint)的概念,这也就是我们上文所提及的特定的位置,基于这个设定,用户的程序仅仅会在特定的情况下生成oopMap,同理在垃圾回收时,也要求所有线程达到安全点后才能够暂停并进入STW从而开始进行初始标记、最终标记等操作:

在这里插入图片描述

例如下面这段代码:

Object o=new Object();

对应汇编码如下,可以看到0x00000000031ffb8fcall指令,它指明偏移量40-852处有一个普通对象指针Oop(Ordinary Object Pointer)

0x00000000031ffb80: mov    $0xf5,%edx
  0x00000000031ffb85: mov    %ecx,%ebp
  0x00000000031ffb87: mov    %rbx,0x28(%rsp)
  0x00000000031ffb8c: data16 xchg %ax,%ax
  0x00000000031ffb8f: callq  0x00000000030957a0  ; OopMap{
   [40]=Oop off=852}
                                                ;*new  ; - java.lang.String::<init>@58 (line 205)
                                                ; - java.lang.String::substring@52 (line 1933)
                                                ;   {
   runtime_call}

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

对于安全点上的线程中断策略,大体来说是有两种:

  1. 抢占式:当需要进入安全点时,JVM会主动挂起所有的用户线程,如果线程未在安全点则等到该线程进入安全点进入安全点并完成中断。这种做法最大的缺点就是时间不可控即很可能存在性能不稳定亦或者吞吐量的波动,所以截至目前还有那款虚拟机采用抢占式的方式完成线程中断。
  2. 主动式:这种方式是让线程去维护一个标志位,需要进入安全点时修改该变量,用户线程就会在合适的时机检查这个变量值,如果这个值为真时就进入安全点。

线程什么时候需要进入安全点

除了常见的垃圾回收标记触发STW使得所有线程需要进入安全点以外,对应的进入安全点的时机还有:

  1. 使用jstatjmapjstack等命令,为保证监控堆栈信息的实时正确性,所有线程需要STW并进入安全点暂停。
  2. JDK8默认情况下定时进入安全点,保证一些需要进入安全点的操作能够及时运行。
  3. JIT编译代码优化例如:OSR(栈上替换即一种运行时替换栈帧的技术)或者去优化即Bailout(将JIT编译后的代码回退,解释器模式),因为可能存在执行指令的变化,线程就需要进入安全点。
  4. java agent需要对类进行增强导致类重新定义,需要修改类的相关信息,所以需要进入安全点。
  5. 高并发情况下,锁升级机制会涉及偏向锁撤销,需要进入STW所以也需要进入安全点。

JVM如何保证线程高效进入安全点

我们以线程运行JIT编译好的代码为例,它的设计与实现步骤为:

  1. JVM初始化一个异常处理器,专门捕获对应的page fault缺页中断异常。
  2. JIT编译代码期间,会基于我们上述的规则在特定位置插入一条精简的指令,作为安全点检查。
  3. VM线程通知当前线程进入安全点,将线程内部维护的内存页即polling page设置为不可读。
  4. 线程执行这条机器码指令发现内存页不可读,触发缺点中断。
  5. 异常处理器捕获这个异常,线程进入安全点。

在这里插入图片描述

对应的我们也给出这段精简的汇编码指令,即test %eax,0x160100 ; {poll} 这段指令,这段指令本质上就是执行poll操作检查安全点,尝试访问线程内存页对应地址为0x160100,如果发现不可访问则触发缺页中断进入安全点:

0x01b6d627: call   0x01b2b210         ;<

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2355834.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nginx — http、server、location模块下配置相同策略优先级问题

一、配置优先级简述 在 Nginx 中&#xff0c;http、server、location 模块下配置相同策略时是存在优先级的&#xff0c;一般遵循 “范围越小&#xff0c;优先级越高” 的原则&#xff0c;下面为你详细介绍&#xff1a; 1. 配置继承关系 http 块&#xff1a;作为全局配置块&…

线性代数—向量与矩阵的范数(Norm)

参考链接&#xff1a; 范数&#xff08;Norm&#xff09;——定义、原理、分类、作用与应用 - 知乎 带你秒懂向量与矩阵的范数(Norm)_矩阵norm-CSDN博客 什么是范数&#xff08;norm&#xff09;&#xff1f;以及L1,L2范数的简单介绍_l1 norm-CSDN博客 范数&#xff08;Norm…

【业务领域】电脑主板芯片电路结构

前言 由前几期视频合集(零基础自学计算机故障排除—7天了解计算机开机过程)&#xff0c;讲解了POST的主板软启动过程&#xff1b;有不少网友留言、私信来问各种不开机的故障&#xff0c;但大多网友没能能过我们的这合集视频&#xff0c;很好的理清思路&#xff0c;那这样的情况…

pandas读取Excel数据(.xlsx和.xls)到treeview

对于.xls文件&#xff0c;xlrd可能更合适&#xff0c;但需要注意新版本的xlrd可能不支持xlsx&#xff0c;不过用户可能同时需要处理两种格式&#xff0c;所以可能需要结合openpyxl和xlrd&#xff1f;或者直接用pandas&#xff0c;因为它内部会处理这些依赖。 然后&#xff0c;…

JVM——垃圾收集策略

GC的基本问题 什么是GC&#xff1f; GC 是 garbage collection 的缩写&#xff0c;意思是垃圾回收——把内存&#xff08;特别是堆内存&#xff09;中不再使用的空间释放掉&#xff1b;清理不再使用的对象。 为什么要GC&#xff1f; 堆内存是各个线程共享的空间&#xff0c…

马克·雷伯特:用算法让机器人飞奔的人

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 马克雷伯特:用算法让机器人飞奔的人 一、天才的起点 在机器人领域,有一个名字如雷贯耳——马克雷伯特(Marc Raibert)。作为波士顿动力公司(Boston…

信创系统资产清单采集脚本:主机名+IP+MAC 一键生成 CSV

原文链接&#xff1a;信创系统资产清单采集脚本&#xff1a;主机名IPMAC 一键生成 CSV Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇在信创终端操作系统上自动批量采集主机名、IP 和 MAC 并导出为 CSV 表格的实战文章&#xff01;本方案使用 sshpass 和 Bash 脚本…

SpringBoot获取用户信息常见问题(密码屏蔽、驼峰命名和下划线命名的自动转换)

文章目录 一、不返回password字段二、返回的createTime和updateTime为空原因解决&#xff1a;开启驼峰命名和下划线命名的自动转换 设置返回的日期格式 一、不返回password字段 在字段上面添加JsonIgnore注解即可 JsonIgnore // 在把对象序列化成json字符串时&#xff0c;忽略…

Mac下安装Python3,并配置环境变量设置为默认

下载Python 访问Python官方网站 https://www.python.org/ 首先获得python3安装路径 执行命令&#xff1a; which python3 以我这台电脑为例&#xff0c;路径为&#xff1a;/Library/Frameworks/Python.framework/Versions/3.9/bin/python3 编辑 bash_profile 文件 然后用 vim 打…

Linux-04-用户管理命令

一、useradd添加新用户: 基本语法: useradd 用户名:添加新用户 useradd -g 组名 用户:添加新用户到某个组二、passwd设置用户密码: 基本语法: passwd 用户名:设置用户名密码 三、id查看用户是否存在: 基本语法: id 用户名 四、su切换用户: 基本语法: su 用户名称:切换用…

【进阶】--函数栈帧的创建和销毁详解

目录 一.函数栈帧的概念 二.理解函数栈帧能让我们解决什么问题 三.相关寄存器和汇编指令知识点补充 四.函数栈帧的创建和销毁 4.1.调用堆栈 4.2.函数栈帧的创建 4.3 函数栈帧的销毁 一.函数栈帧的概念 --在C语言中&#xff0c;函数栈帧是指在函数调用过程中&#xff0c;…

【一】 基本概念与应用领域【数字图像处理】

考纲 文章目录 1 概念2005甄题【名词解释】2008、2012甄题【名词解释】可考题【简答题】可考题【简答题】 2 应用领域【了解】2.1 伽马射线成像【核医学影像】☆2.2 X射线成像2.3 紫外波段成像2.4 可见光和红外波段成像2.5 微波波段成像2.6 无线电波段成像2.7 电子显微镜成像2…

NU1680低成本、无固件、高集成度无线充电电源接收器

无线充电 电子产品具有无线充电功能使用会更便利&#xff0c;介绍一款低成本、无固件、高集成度无线充电电源接收器NU1680 原理图和BOM可点绑定资源下载&#xff0c;LC部分电容建议X7R。 Load空载切满载测试 (CC Mode) – 尽量保证电子负载没有过冲 – 电子负载不要从0到满…

2025MathorCup数学应用挑战赛B题

目录 模型建立与求解 1.问题一的模型建立与求解 1.1 搬迁补偿模型设计 1.2 住户是否搬迁的应对策略与分析 1.3 定量讨论 2.问题二的模型建立与求解 2.1 搬迁方案模型的优化介绍 2.2 模型的评估 2.3 模型结果 3.问题三的模型建立与求解 3.1 拐点存在性分析模型的建立 3.2 模型的…

组件的基本知识

组件 组件的基本知识 组件概念组成步骤好处全局注册生命周期scoped原理 父子通信步骤子传父 概念 就是将要复用的标签&#xff0c;抽离放在一个独立的vue文件中&#xff0c;以供主vue文件使用 组成 三部分构成 template&#xff1a;HTML 结构 script: JS 逻辑 style: CSS 样…

Origin绘图操作:图中迷你图绘制

一、背景描述 Origin绘图时&#xff0c;局部数据变化较小&#xff0c;在整体图片中表现为局部曲线重叠在一起&#xff0c;图中y1和y2在x0-2时重叠在一起&#xff0c;需要将局部放大&#xff0c;绘制迷你图 二、实现方法 1.在左边工具栏选择放大镜&#xff0c;按住ctrl在图中…

数据升降级:医疗数据的“时空穿梭“系统工程(分析与架构篇)

一、核心挑战与量化分析 1. 版本演化困境的深度解析 (1) 格式断层的结构化危机 数据转换黑洞:某医疗信息平台(2021-2023)统计显示: 数据类型CDA R1→R2转换失败率R2→FHIR转换失败率关键失败点诊断记录28.4%19.7%ICD编码版本冲突(18.7%)用药记录15.2%12.3%剂量单位标准化…

【GESP】C++三级练习 luogu-B2089 数组逆序重存放

GESP三级练习&#xff0c;一维数组练习&#xff08;C三级大纲中5号知识点&#xff0c;一维数组&#xff09;&#xff0c;难度★☆☆☆☆。 题目题解详见&#xff1a;https://www.coderli.com/gesp-3-luogu-b2089/ 【GESP】C三级练习 luogu-B2089 数组逆序重存放 | OneCoderGE…

Copilot 上线深度推理智能体 Researcher

近日&#xff0c;微软推出两款首创的工作场景推理智能体&#xff1a;Researcher&#xff08;研究员&#xff09;和Analyst&#xff08;分析师&#xff09;。它们能以安全合规的方式访问您的工作数据&#xff08;包括邮件、会议、文件、聊天记录等&#xff09;及互联网信息&…

日常开发小Tips:后端返回带颜色的字段给前端

一般来说&#xff0c;展示给用户的字体格式&#xff0c;都是由前端控制&#xff0c;展现给用户&#xff1b; 但是当要表示某些字段的数据为异常数据&#xff0c;或者将一些关键信息以不同颜色的形式呈现给用户时&#xff0c;而前端又不好判断&#xff0c;那么就可以由后端来控…