阿里三面被虐惨,非让我举例说明,为什么GC需要Stop the World?

news2024/11/16 20:32:35

最近,五哥回忆起4年前在蚂蚁金服三面的经历。关于GC的一个问题,让我记忆深刻。

当聊起来Java GC时,我提到 young gc 和 full gc都会 Stop the world。

”为什么需要 Stop the world“,蚂蚁面试官问道。

我略微怔住,想了一会,回答道:“如果一边垃圾回收,业务线程一边跑,可能清理的不干净吧,也可能有一些对象被错误回收”。 事实上,我没背过这个八股文,只能凭感觉瞎说。本以为这个问题就这么糊弄过去了。

“你可以举例说明下,为什么GC需要Stop the world吗?举个例子说明下?” ,蚂蚁面试继续追问道。

这个追问让我措手不及,一脸懵逼。想了几分钟后,半天也没放出个屁…… 支支吾吾没答出来,只得坦白这个问题没有想清楚,我不会。

大家都明白,为什么需要Stop the world,但要举一个实际例子来证明这一点有难度,就像大家都了解快速排序的原理,但手写非递归版本的快速排序真的很困难。

后来的我花了很久,才想到两个例子来反证这个结论。在此之前,我先啰嗦一下,故事的背景……


故事的背景

2019年的春天,刚毕业两年的我,在忙着换工作,那时候的求职环境还不像今天这么寒冷,大公司的面试机会有很多,即便如此,我也非常珍惜大公司的面试机会,尤其是蚂蚁金服。那一天,我坐地铁10号线,去朝阳区蚂蚁金服的办公点——环球金融中心 现场面试,在我看来,这个大楼的名字和蚂蚁金服四个字一样,非常高大上。算上电话面试,今天是第三面,如果面试通过,不出意外的话,后面没有技术面了,应该就能拿到Offer。 心想着,终于可以拿到一个满意的Offer了, 于是既兴奋又紧张的走进了蚂蚁金服。

我没有想到,两个小时后,我会灰溜溜的出来~

当时的我准备得十分充分,我先用小公司、中型公司的面试机会练手,像蚂蚁金服类的大公司留到最后再面试,目的是一击必中,不留遗憾。在当时,我已经有十几轮的面试经验了,自我介绍和项目介绍背的滚瓜烂熟,常见八股文,简单leetCode完全难不倒我。甭管实力如何,至少在心理上我十分自信。

然而蚂蚁金服的面试官从浅入深,在各方面盘问我的技术实力。我的印象是:他们从一个点开始问,一直问到底,问到我不会为止,我一度接近崩溃……。这些问题我努力回忆了一下,可以 # 点击查看8家大厂后端面试题

为什么需要Stop the world

比较官方的解释如下

分析工作必须在一个能确保一致性的快照中进行

一致性指整个分析期间整个执行系统像被冻结在某个时间点上

如果出现分析过程中对象引用关系还在不断地变化,则分析结果的准确性无法保证。

官方给的解释中,重点在强调,GC的分析要确保在一个一致性的视图之上,否则无法保证垃圾回收的准确性。这和我说的几乎一样,“有一些对象可能会被错误回收”,只不过官方的说法更加专业。但是官方并没有给出具体的例子…… 这需要我们自己探索。

垃圾回收算法中的标记工作

在Java堆中,存放着所有Java的对象实例。在进行垃圾收集之前,JVM需要确定哪些对象已经不被使用(即垃圾),哪些对象仍然被使用。为了判断对象是否是“垃圾”,JVM采用了可达性分析算法。

可达性分析算法 是指通过指定 GC Root 根对象,从根对象开始搜索引用的对象,通过引用链条,层层遍历链条上的对象,可以到达的对象不可被垃圾回收。而最终没有被搜索遍历到的对象,则为 不可达对象,应该被垃圾回收。

JVM中的 GC Root根对象包括如下:

  1. 虚拟机栈引用的对象
  2. 本地方法栈内JNI(本地方法)引用的对象
  3. 方法区中常量引用的对象(字符串常量池)
  4. 所有被同步锁synchronized持有的对象
  5. Java虚拟机内部的引用

垃圾回收必须要先标记出垃圾对象,才可以进行后续的清理工作。无论是采用 标记-整理算法还是标记-清理算法。标记工作都是必不可少的。

如上文指出,JVM 明确标记工作进行时,业务线程必须暂停执行!

下面我提出两个例子说明下,如果业务线程没有被暂停,会造成什么后果!

使用反证法证明,为什么需要Stop the world

接下来,我通过一段代码,证明这个结论: 如果不暂停业务线程,对象会被错误的垃圾回收!

9782b293bc5e83cc2dc31d763babee67.jpeg

以上代码中,声明了 target static静态常量,引用了Context类型对象。因为被常量引用,target在GC Root上。也就是说垃圾回收时,会以target为根,开始遍历。正常情况下target引用的对象不会被回收…… 但如果不暂停业务线程后,Context对象会被错误回收!

在main方法中一共有 4 步。

首先 第一步:定义 temp变量为 null;

第二步:将target引用赋值给 temp;

第三步:将target 变量指向null,此时Context对象只被 temp 变量引用。

最后一步第四步,调用temp.toString();

接下里我开始分析,假设开启垃圾回收时,不暂停业务线程,垃圾回收线程和业务线程一起并发执行,会有哪些潜在的坑点!

为了清晰期间,我使用表格来表示时间线。在此例中,两个线程为 main 线程和垃圾回收标记线程。

2e64332265db93241f5f77289814df02.jpeg

通过上图的分析,我们发现,原Context对象,在被其他变量引用的情况下,被错误的垃圾回收,造成了不可预测的情况发生。

原因是,当垃圾回收线程检查 main 线程时,发现无法通过 main 线程的虚拟机栈引用 Context 对象。这是因为 temp 还未被赋值。于是,垃圾回收线程转而遍历 target 变量。在此时间窗口内,main 线程从 target 变量中获取到 Context 对象的引用,并将 target 变量设置为null。回到垃圾回收线程,它检查到 target 变量为null。在垃圾回收线程看来,无论是main线程还是 target 变量,都没有引用到 Context 对象。因此,垃圾回收器回收了 Context 对象。然而,main 线程中的 temp 变量仍然持有 Context 对象。在这种情况下,对 Context 对象的任何操作都将变得不可预测。

这个过程略微有些混乱,可以通过参考时间线表格来更好地理解。

此时再去理解 JVM官方文档给的原因

分析工作必须在一个能确保一致性的快照中进行,一致性指整个分析期间整个执行系统像被冻结在某个时间点上

正是因为 main 线程和垃圾回收线程同时执行,导致垃圾回收在分析 main 线程的虚拟机栈和target变量时,并没有在一个冻结的时间上,而是在先后的两个时间点分析对象是否可达。在先后时间的窗口期内,Context 对象被赋值给其他对象,但是垃圾回收线程对此毫无感知…… 最终当 Context 被错误回收以后,业务线程访问 Context时,将出现极其诡异且致命的问题……

通过反证法,我们证明出,如果不暂停业务线程,那么无法进行准确的垃圾回收工作。

其他例子

还有其他例子可以佐证。

例如只有两行代码 的一段程序。

Context temp = null;

temp = new Context();`

main 线程中,创建一个新的 Context对象,此时只有 temp 变量持有 Context对象,恰好垃圾回收线程在遍历 main 线程的 虚拟机栈时, temp变量还为null;

于是在垃圾回收标记完成后,发现Context对象不可达,于是被当成垃圾回收了……

如果不暂停业务线程,在垃圾回收期间新创建的对象,有可能会被错误的回收掉,这真的太可怕了。

之所以可能出现这么离谱的现象, 原因就在于,业务线程和垃圾回收线程并行执行,谁也无法预知 垃圾标记的工作和 引用关系的变化 谁先谁后。

只有当业务线程被暂停,才能保证垃圾回收的标记是准确的

假如业务线程被暂停,还会有问题吗?

第二个例子中,假设在 第一行代码后 Context temp = null; 业务线程被暂停。由于 Context对象还未创建,所以不会有对象被回收。

假设在 第二行代码执行后,被暂停。由于 main线程 temp 变量还持有 Context对象引用,所以 Context对象不会被垃圾回收。

回到第一个表格的代码,当main线程被暂停后,无论被暂停在 哪一行代码,垃圾税收标记工作都不会出现任何问题。读者可以自行假设论证一下。

总结

通过 列举两个反例,通过反证法证明 业务线程必须被暂停,才可以进行垃圾回收标记工作。

4年前的面试,我被问到这个问题时,我的破解思路是,有两个业务线程,互相修改引用关系,垃圾回收判断垃圾对象,会出现错误。但是两个业务线程的场景,实在复杂,我无法举出实际的例子。其实 只需要一个main线程 和垃圾线程对比分析,就能说明问题,根本不需要两个业务线程来证明这个问题。

一个线程尚且出问题,由此可见,业务逻辑千奇百怪,当存在上千个业务线程时,如果不暂停业务线程,就进行垃圾回收,该多么可怕!

一般情况下,在聊GC时,没有面试官会深入到 为什么需要Stop the world 这类问题,但是阿里的面试官独辟蹊径,成功的卷到我。

这个问题虽然看起来简单,但真要现场举例说明,还是有难度的!

我当时没有回答上来这个问题,一度以为被挂掉,但最终这轮技术面试还是通过了…… 也是一个惊喜

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

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

相关文章

WH4530A可检测0-100cm环境光+距离检测功能

台湾旺泓推出的WH4530A是一款结合了先进环境光传感器(ALS)先进接近传感器(PS)和高效率的红外LED灯三合一为一体的光距感接近传感器;可测距范围0-100cm;采用I2C接口,可实现超高灵敏度、精准测距检测范围广等…

设备管理软件有什么用?如何让维修工作智能化?

随着数字化和人工智能技术的不断发展,设备管理软件已经成为了一种智能化的管理方式,它能够整合设备设施的维修资源,实现全生命周期的设备设施管理。这种软件可以帮助机构单位更好地跟踪和管理设备设施的维修请求,提高维修效率和管…

OA+CRM+HR+ERP 客户关系 进销存 财务 办公审批系统源码

功能介绍 1、个人中心 电话薄:主要用于添加联系人信息,相当于通讯录功能,可以存贮相关联系人的基本信息,姓名、联系方式、地址、邮箱等。 工作日志 :主要用于记录个人工作生活中大小事情的备忘,相当于备…

红队专题-从零开始VC++C/S远程控制软件RAT-MFC-超级终端

红队专题 招募六边形战士队员[16]超级终端(1) 招募六边形战士队员 一起学习 代码审计、安全开发、web攻防、逆向等。。。 私信联系 [16]超级终端(1) 服务端 — 本地打开cmd — 接收命令 — 执行 — 发送回显 客户端 — 远端发送命令 — 接收回显 发送开启cmd命令 --- 接受…

Rectangle:掌控你的Mac视窗,提升工作效率

你是否曾经在Mac上同时处理多个窗口,却因为无法有效管理而感到困扰?现在,一款全新的窗口管理工具正在改变这一切,它就是Rectangle。 Rectangle是一款简单而强大的窗口管理工具,适用于Mac系统。它改变了传统的窗口管理…

深度学习AI识别人脸年龄

以下链接来自 落痕的寒假 GitHub - luohenyueji/OpenCV-Practical-Exercise: OpenCV practical exercise GitHub - luohenyueji/OpenCV-Practical-Exercise: OpenCV practical exercise import cv2 as cv import time import argparsedef getFaceBox(net, frame, conf_thresh…

拆解软件定义汽车:OS突围

软件作为智能汽车的核心组成部分,由于自身较为独立和复杂的IT学科体系,其技术链路、产业分工、价值分配、商业模式相对硬件产品(如域控、激光雷达、摄像头等硬件)而言,在汽车产业内探讨和传播相对较少。 11月3日&…

GoLong的学习之路,进阶,语法之并发(并发错误处理)补充并发三部曲

这篇文章主要讲的是如何去处理并发的错误。 在Go语言中十分便捷地开启goroutine去并发地执行任务,但是如何有效的处理并发过程中的错误则是一个很棘手的问题。 文章目录 recovererrgroup recover 哦对,似乎没写错误处理的文章。后面补上。 首先&…

Mac 本地部署thinkphp8【配置环境】

PHP开发工具 我这里选择的是VSCode,里面安装PHP插件 把thinkphp的项目放到 切换到phpenv ![在这里插入图片描述](https://img-blog.csdnimg.cn/a15cc442fab74754ad86d74f6d9942e5.png URL重写如果不改,在请求的时候地址是这样的‘http://tp.com/index.php…

数据可视化模板案例:制造业提高生产力的关键

一、模板背景 在这个信息爆炸的时代,数据对于企业的成功至关重要。制造业作为全球经济的重要组成部分,如何有效利用数据提高生产效率、降低成本、优化决策,已成为行业关注的焦点。 二、方案思路 配⾊ - 科技蓝,贴合⼯业主题。 …

【算法与数据结构】78、90、LeetCode子集I, II

文章目录 一、题目二、78.子集三、90.子集II三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、78.子集 思路分析:【算法与数据结构】77、LeetCode组合。本题可以参考77题的组合问题代码&#xff0…

/etc/init.d/functions: Syntax error: “(“ unexpected (expecting “done“)

一.问题描述: ubuntu系统安装服务时报错: 二.问题解析: Ubuntu安装时默认使用dash,shell脚本命令失败,需要安装bash来运行,长期解决该问题就是重新配置dash 三:问题解决: sudo dpkg-reconfi…

迅为龙芯2K1000开发板虚拟机ubuntu启动root用户

作为嵌入式开发人员,系统的所有权限都要为我们打开,所以我们不必像运维那样,对 root 用户非常敏感,所以安装完 ubuntu 系统以后,我们要启用 root 用户。 首先我们打开 ubuntu 控制终端,然后在终端里面输入…

wireshark抓包并进行Eigrp网络协议分析

路由协议 Eigrp ​ EIGRP:Enhanced Interior Gateway Routing Protocol 即 增强内部网关路由协议。也翻译为 加强型内部网关路由协议。 EIGRP是Cisco公司的私有协议(2013年已经公有化)。 EIGRP结合了链路状态和距离矢量型路由选择协议的Cisco专用协议&a…

银行数据中心机房动力环境监控系统设计与优化

安科瑞电气股份有限公司 上海嘉定201801 摘要:结合银行数据中心建设项目,设计银行数据中心机房动力环境监控系统,分析银行数据中心机房监控对象、搭建系统监控架构,给出监控实现方法,*后针对运行一段时间出现的问题&a…

关于淘宝API接口你必须了解的API2.0

据说API从1.0升级到2.0啦?今天我们来聊一聊关于淘宝API接口你必须了解的API2.0 然而 作为新手小白 …… 并不懂API是毛线 好吧 …… 今天 我们就来上一堂小白入门课 几句话聊聊API 高级淘客 请忽略 请批评 请交流 还有请看到最底下 有重磅消息&#xf…

人大女王金融硕士毕业生:追风而遇、沐光同行;心羽为翼,不负韶华!

中国人民大学-加拿大女王大学金融硕士2022-2023级行业高管班 新加坡大东方人寿北京代表处首席代表 01、社会发展推动金融业持续迭代,为更好应对未来挑战,持续学习和自我升级非常重要! 2015年以来,新一代数字化和智能化信息技术…

halcon获取轮廓属性的时候报错:Contour attribute not defined(HALCON错误代码:3261)

报错截图: 在使用以下算子,获取xld的distance属性时,或者其他属性时报错。 get_contour_attrib_xld (ObjectSelected, distance, Attrib) 如果是属性报错。这里需要在调用获取轮廓属性之前先获得轮廓之间的距离。 使用以下算子:…

如何构建可视化设计中的视觉层次?

【什么是视觉层次感】 第一层级:主导元素,即最重要的视觉信息。能够很清晰的传达最重要的信息,你的主导层级通常由图形或者重要的视觉原色组成; 第二层级:应该是数据焦点,引导用户查看重要的数据指标&…

解决@Autowired警告

一.前言 再使用springboot自动注入Autowired注解时,下方会出现波浪线警告,这是什么原因呢?我们细看提示说明已经说的很清楚了,Field injection is not recommended “不建议使用字段注入”,字段注入是指通过直接将依赖项注入到类的字段中来实现依赖注入。这种方式存在一些问题…