GC的前置工作,聊聊GC是如何快速枚举根节点的

news2024/9/28 5:33:41

本文已收录至GitHub,推荐阅读 👉 Java随想录

原创不易,注重版权。转载请注明原作者和原文链接

文章目录

    • 什么是根节点枚举
    • 根节点枚举存在的问题
    • 如何解决根节点枚举的问题
    • 安全点
    • 安全区域

上篇文章中我们留下了个坑:「 根节点枚举」,这篇文章就把坑填上。

在上篇文章中我们知道了HotSpot使用的是可达性分析算法,该算法需要进行根节点枚举。

但是查找根节点枚举的过程要做到高效并非一件容易的事情,现在Java应用越做越庞大,光是方法区的大小就常有数百上千兆,里面的类、常量等更是「恒河沙数」(一种修辞手法),若要逐个检查以这里为起源的引用肯定得消耗不少时间。

大家可以思考下,如果你是JVM的开发者,你会怎么去做?

前面的文章大伙可能有点忘了,那么首先我们对根节点枚举,先做个复习(我绝对不是在混字数)。

什么是根节点枚举

顾名思义,根节点枚举就是找出所有的GC Roots

当然要成为GC Roots是有条件的,固定可作为GC Roots的对象包括以下几种(摘抄自《深入理解虚拟机 第3版》):

  • 在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。
  • 在方法区中常量引用的对象,譬如字符串常量池(String Table)里的引用。
  • 在本地方法栈中JNI(即通常所说的Native方法)引用的对象。
  • Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器。
  • 所有被同步锁(synchronized关键字)持有的对象。
  • 反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。

上面说的这些,大伙肯定记不住,反正总结就一句话:固定可作为GC Roots的节点主要在全局性的引用(例如常量或类静态属性)与执行上下文(例如栈帧中的本地变量表)中。

根节点枚举存在的问题

迄今为止,所有收集器在根节点枚举这一步骤时都是必须暂停用户线程的。因此毫无疑问根节点枚举与之前提及的整理内存碎片一样会面临相似的「Stop The World」的困扰。

根节点枚举必须在一个能保障一致性的快照中才得以进行——这里「一致性」的意思是整个枚举期间执行子系统看起来就像被冻结在某个时间点上。

为什么要这么做?

试想一下,你妈给你打扫房间,你妈一边打扫,你一边丢垃圾,房间永远也打扫不干净。

所以本质上来说,根节点枚举遇到的问题,就是并发问题。

如果不「冻结」的话,根节点集合的对象引用关系在不断变化,那么分析结果准确性也就无法保证。

所以即使是号称停顿时间可控,或者(几乎)不会发生停顿的CMS、G1、ZGC等收集器,在枚举根节点这一步也是必须要停顿的。

弄明白问题之后,我们开动脑筋想想怎么解决。

如何解决根节点枚举的问题

目前主流Java虚拟机使用的都是「准确式垃圾收集」。

所谓准确式垃圾收集是指垃圾收集器能够精确地确定内存中哪些区域被对象引用,哪些区域已经不再使用,并且可以立即回收不再使用的内存。

在准确式垃圾收集中,垃圾收集器需要知道每一个引用类型变量(包括实例字段、静态字段、本地变量和输入参数等)在内存中的确切位置,以及这个位置是否正在被引用。

这样,当垃圾收集器需要进行回收时,它就可以精确地找到并回收那些不再有任何引用的对象所占用的内存。

相对应的,还有一种叫做「保守式垃圾收集」,它不能精确地识别所有的引用,只能保守地认为所有看起来像对象引用的值都可能是引用。这种方式可能会导致某些实际上可以被回收的内存得不到回收。

HotSpot采用的是准确式垃圾收集

所以当用户线程停顿下来之后,其实并不需要一个不漏地检查完所有执行上下文和全局的引用位置,虚拟机应当是有办法直接得到哪些地方存放着对象引用的。

在HotSpot的解决方案里,是使用一组称为OopMap的数据结构来达到这个目的。OopMap可以理解为就是映射表,存储栈上的对象引用的信息,这是一种空间换时间的做法。

在 GC Roots 枚举时,只需要遍历每个栈桢的 OopMap,通过 OopMap 存储的信息,快捷地找到 GC Roots,这样就不需要进行全局扫描。

用大白话说,其实就是用类似映射表这种手段记录下来引用关系,时不时去更新下映射表,然后根节点枚举只需要扫描映射表就知道哪些地方存放引用了,而不用去进行全局扫描。

OK,弄明白之后,问题又来了,既然OopMap是一个映射表,这个表什么时候被更新?

你可能会觉得这有啥难的,引用更新的时候同步去更新映射表不就完事了吗,然而事情并没有想的那么简单。

要知道引用关系变化是十分频繁的,如果引用每变化一次就更新对应的OopMap,那将会需要大量的额外存储空间,这样垃圾收集伴随而来的空间成本就会变得无法忍受的高昂。

安全点

解决这个问题的办法就是「安全点」,事实上,只是在「特定的位置」记录了这些信息,这些位置被称为安全点(Safepoint)。

因此GC不是随时随地来的,得到达安全点时才可以开始GC。

所以流程我们就清楚了:先是到达安全点,然后更新OopMp,然后进行根节点枚举,找到GC Roots,开始GC。

安全点的选举,一般会在如下几个位置出现:

  • 循环的末尾
  • 方法临返回前
  • 调用方法之后
  • 抛异常的位置

到这里为止,貌似问题我们都解决了,but,还有一个问题我们需要考虑,我们前面说了系统要在某个时间点处于「冻结」状态,那么如何在垃圾收集发生时让所有线程都跑到最近的安全点,然后停顿下来?

有两种方案可供选择:抢先式中断(Preemptive Suspension)主动式中断(Voluntary Suspension)

  • 「抢先式中断」:不需要线程的执行代码主动去配合,在垃圾收集发生时,系统首先把所有用户线程全部中断,**如果发现有用户线程中断的地方不在安全点上,就恢复这条线程执行,让它一会再重新中断,直到跑到安全点上。**现在几乎没有虚拟机实现采用抢先式中断来暂停线程响应GC事件。

  • 「主动式中断」:当垃圾收集需要中断线程的时候,不直接对线程操作,仅仅简单地设置一个标志位,各个线程执行过程时会不停地主动去轮询这个标志,一旦发现中断标志为真时就自己在最近的安全点上主动中断挂起。

安全点的设计似乎已经完美解决如何停顿用户线程,但是仍然有问题,安全点机制保证了程序执行时,在不太长的时间内就会遇到可进入垃圾收集过程的安全点。但是,程序「不执行」的时候呢?

所谓的程序不执行就是没有分配处理器时间,典型的场景便是用户线程处于Sleep状态或者Blocked状态,这时候线程无法响应虚拟机的中断请求,不能再走到安全的地方去中断挂起自己。

对于这种情况,JVM引入安全区域(Safe Region)来解决。

安全区域

**安全区域是指能够确保在某一段代码片段之中,引用关系不会发生变化。**因此,在这个区域中任意地方开始垃圾收集都是安全的。我们也可以把安全区域看作被扩展拉伸了的安全点。

当用户线程执行到安全区域里面的代码时,首先会标识自己已经进入了安全区域。

那样当这段时间里虚拟机要发起垃圾收集时就不必去管这些已声明自己在安全区域内的线程了。

当线程要离开安全区域时,它要检查虚拟机是否已经完成了根节点枚举(或者垃圾收集过程中其他需要暂停用户线程的阶段)。

如果完成了,那线程就当作没事发生过,继续执行;否则它就必须一直等待,直到收到可以离开安全区域的信号为止。

好了,本篇文章到这结束咯。结合上篇可达性分析,我们一步步揭开了GC的神秘面纱,然而路还很远,仍然还有很多东西是需要我们去学习了解的。


感谢阅读,如果本篇文章有任何错误和建议,欢迎给我留言指正。

老铁们,关注我的微信公众号「Java 随想录」,专注分享Java技术干货,文章持续更新,可以关注公众号第一时间阅读。

一起交流学习,期待与你共同进步!

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

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

相关文章

计网第三章(数据链路层)(四)

目录 一、MAC地址和IP地址以及ARP协议 1.MAC地址: 单播MAC地址: 广播MAC地址: 多播MAC地址: 2.IP地址: 3.IP地址和MAC地址: 1.什么情况下使用? 2.IP地址和MAC地址填写位置?…

保障用户观影体验 极米推出首款搭载超级混光技术投影仪极米RS Pro 3

随着投影市场的日渐蓬勃,倒推了投影技术的研发创新,投影仪产品在最近几年已经逐步进入到家庭空间,成为很多家庭不可或缺的家电产品,不论是客厅还是卧室,或者是户外露营等,投影仪的家用场景已经拓展到了人们…

ps2024后期调色滤镜插件使用教程图解

Exposure是一款常见的ps调色滤镜插件,相信许多朋友都曾经用过它。一个优秀的摄像师不仅需要懂得摄像技巧,还要掌握图像的后期调色窍门。那么,后期调色软件哪个好,后期调色教程图解,接下来一起来了解一下吧。 一、后期…

为何Ping不通啊?

为什么Ping不通啊!求指点? 友情提醒,这个问题难度系数初级难度(CCNA),只适合初级读者阅读,避免浪费宝贵时间。 Q1: 为何PC1能Ping通PC2?或反之亦然? PC1主观认为PC2和自…

YOLO目标检测——血管瘤数据集下载分享

血管瘤数据集在医学领域的研究和临床应用中起着重要的作用。它可以用于开发和评估血管瘤检测和分割算法,帮助医生准确地定位和诊断血管瘤。此外,血管瘤数据集还可以用于研究血管瘤的生长规律、预测血管瘤的发展趋势等。 数据集点击下载:血管瘤…

云windows iis部署vue前端项目 步骤

工作记录 第一步 先进行vue项目打包 npm run build打包后会产生一个dist文件 然后将前端全部文件传到想要部署的windows上 这个一步直接远程连接 复制粘贴就可以 第二步 打开iis 添加网络 网站名称输入你想要用的二级域名 (需要到**云上报备下 我这个用的是阿里…

自动化测试工具Selenium的语法续.

OK,那么上篇博客我们介绍了如何搭建基于Javaselenium的环境,并且使用selenium的一些语法给大家演示了如何进行自动化测试的案例,那么本篇博客我们来继续学习selenium的一些其他的比较重要的语法,感谢关注,期待三连~ 目…

快速学会创建uni-app项目并了解pages.json文件

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 前言 创建 uni-app 项目 通过 HBuilderX 创建 pages.json pages style globalStyle tabBar 前言…

从零做软件开发项目系列之二——需求调研

在接到软件开发任务之后,第一件要做的事情就是进行需求调研工作,基于前期的沟通以及合同向用户了解具体需求,从而有针对性地开展后续工作。整个调研过程分为调研准备,调研实施,需求分析。 1 调研准备 俗话说&#x…

基于微信小程序的宠物领养平台的设计与实现(Java+spring boot+微信小程序+MySQL)

获取源码或者论文请私信博主 演示视频: 基于微信小程序的宠物领养平台的设计与实现(Javaspring boot微信小程序MySQL) 使用技术: 前端:html css javascript jQuery ajax thymeleaf 微信小程序 后端:Java…

【工程实践】使用pandas的记录

前言 工作中处理数据时,经常需要使用pandas,记录一些工作中使用pandas的习惯。 1. 合并数据 #读取原始数据 data1 pd.read_excel(/home/zhenhengdong/WORk/Classfier/Dates/Original/1.xlsx) data2 pd.read_excel(/home/zhenhengdong/WORk/Classfier/…

石油化工钻井消防vr虚拟教学实训增加学员参与感

随着石油化工企业的生产规模和数量不断扩大,石油化工火灾事故常有发生,给企业及当地居民造成难以挽回的严重损失,为了避免石油化工火灾安全事故发生,VR安全培训公司深圳华锐视点制作的石油化工火灾vr模拟应急救援系统,…

java+springboot+mysql小区自来水实时监控管理系统

项目介绍: 使用javaspringbootmysql开发的小区自来水实时监控管理系统,系统包含超级管理员,系统管理员、用户角色,功能如下: 超级管理员:管理员管理;楼栋管理;租户管理、用水管理&…

远程真机测试为什么需要应用性能指标监控?

我们在使用app、小程序等手机应用的时候,经常会发生“卡死“等现象。”卡死“会让用户认为你的app不可信,从而引发删除等情况。我们辛辛苦苦、花费大量精力和费用推广的app就失败了。 因此,我们就需要知道,app在使用时候&#…

ROS_LINUX入门学习笔记=2=

B站ros机器人工匠阿杰入门教程 rqt_robot_steering 控制小乌龟 在index ros .rog中查找相关的包:rosindex 下图是rqt_robot_steering的简介 其中可以查看github源码地址 website可以查看效果图 下载相关的包 sudo apt install ros-kinetic-rqt-robot-steering r…

项目实战笔记2:硬技能(上)

序: 本节串讲了项目管理硬技能,有些术语可以结合书或者网上资料来理解。没有想书上讲的那样一一列举。 做计划 首先强调为什么做计划? 计划就是各个角色协同工作的基准(后面做风险监控、进度的监控),贯穿于…

【华为认证】HCIA真题20道(看看HCIA的技术你掌握了多少)

正在备考华为认证的小伙伴应该知道,除了理论知识外,刷题也相当重要,周工这里有一份HCIAHCIP-Datacom带解析的最新题库 点赞留言 即可领取。 下图所示,主机A和主机B使用哪种网络设备可以实现通信?( &…

设计模式-工厂设计模式

核心思想 在简单工厂模式的基础上进一步的抽象化具备更多的可扩展和复用性,增强代码的可读性使添加产品不需要修改原来的代码,满足开闭原则 优缺点 优点 符合单一职责,每个工厂只负责生产对应的产品符合开闭原则,添加产品只需添…

骨传导耳机品牌推荐,精选十大骨传导耳机品牌推荐

随着手机作为大众日常生活不可分割的一部分,使用耳机也成为了许多人的日常。相较于有线耳机,有越来越多的人愿意去选择无线耳机,骨传导耳机的受众也进一步提高了,那么面对市面上眼花缭乱的品牌,该如何选择呢&#xff1…

怎样清理电脑内存?分享4个快速清理方法!

“求救求救!电脑总是没内存怎么办啊?明明没有存很多东西啊,电脑容量也很大,总是没内存真的很影响心情哎!有什么方法可以解决这个问题吗?” 电脑内存的清理是维护系统性能的重要步骤之一。如果电脑内存不足&…