您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

暴力破解美团最新JVM面试题:无限执行

时间:2022-03-16 09:15:11  来源:  作者:大数据架构师

昨天JAVA圈,美团曝出了一道变态级面试题:为什么栈溢出后线程没有崩溃?为什么这段代码会永远执行下去?

暴力破解美团最新JVM面试题:无限执行

 

我的几个交流群、VIP群,争论不休,看大家都是在Java层找答案。很明显,这个问题的答案不在Java层,接下来咱们分析下这个问题,然后一起去找答案,争取下次被问到,一举击溃面试官的心理防线:偶滴乖乖,是这道题难度太小还是我太菜?

我会按照看到这个问题我是如何分析如何做实验如何得出结论,层层递进展开,你读起来应该会越来越嗨皮!瓦特?你没嗨皮?你是不是没看懂哦?

01

我的第一反应

我的第一反应是catch Error会永远执行,那catch Exception呢?接下来上代码

暴力破解美团最新JVM面试题:无限执行

 

看运行结果

暴力破解美团最新JVM面试题:无限执行

 

会报栈OOM

我脑海中马上想到两个问题:

1、这个栈深度是多少时抛出的?

2、为什么catch Exception会抛出?

 

怎么查看栈深度呢?JVM提供了相关方法吗?木有!我们通过linux命令来统计

暴力破解美团最新JVM面试题:无限执行

 

报栈OOM时,栈的深度是1024,这个数字大家记一下,后面还会讲到,很关键!

接下来第二个问题,为什么catch Exception会抛出OOM?其实对于这段代码,这个问题就是坑,因为栈溢出抛出的是StackOverflowError,你catch Exception是无效的,等同于

暴力破解美团最新JVM面试题:无限执行

 

什么?你不信?你把代码改成这样,看看catch代码块会不会执行

暴力破解美团最新JVM面试题:无限执行

 

02

第二段探索

研究完了我的第一反应并得到答案以后,我就开始了我的第二段探索:这个Java程序能够无限执行,这个能力是操作系统自带的还是JVM自己开发出来的?

我们来看看操作系统是否具备让程序永远运行的能力。怎么测试呢?需要你懂一点Linux多线程相关的东西。不懂也没关系,看我演示的现象及结论即可。底层内功重不重要,从这里可见一斑。

暴力破解美团最新JVM面试题:无限执行

 

可以看到,Linux系统默认是不支持程序无限执行的

为什么最后会报段错误呢?因为Linux系统创建线程,默认的栈大小是8M,程序无限递归把8M用光了,但是程序还不会终止,不自觉会用到8M之外的内存

这里面还有个隐含知识点,栈图,没有这个基础你可能很难理解上面讲的,放个图帮助你理解

暴力破解美团最新JVM面试题:无限执行

 

03

第三段探索

既然Linux系统没有提供这样的能力,然JVM能如此,大胆猜想可能的原因:

1、JVM改变了系统默认栈大小8M,可能改成了很大很大。如果是这样,那我们看这段程序的无限执行其实是假象,如果让它一直跑,跑很久很久,可能它就over了。

2、JVM内部做了优化,比如栈帧回溯、递归内联、尾递归优化。验证这个的时候还得考虑方法执行的两个阶段:解释执行,执行JIT及时编译后的代码。是真滴复杂!

 

我们开始看下JVM的主线程有没有改线程栈的默认大小,改成了多少。这个要怎么看?单步调试openjdk

暴力破解美团最新JVM面试题:无限执行

 

JVM把改成了1M。

JVM的虚拟机栈是在操作系统的线程栈上进行拓展的,Linux系统的默认线程栈是8M,如果是递归调用,一下就跑完了。但是美团的这段程序,很明显跑了很久都没结束,所以这种情况pass,只剩最后一种情况。

 

04

第四段探索

前面提到了两个关键的东西:栈深度1024,如果程序递归调用把线程栈用光了会报段错误。这两个玩意这里都要用上。开始探索

咱们先就之前的三段探索得出的经验进行头脑风暴一下:程序无限执行的能力,Linux没有提供,但是这段Java程序能够无限执行,说明这个能力是JVM赋予的。

那JVM如何做到的呢?首先,栈的内存大小决定了,一个程序的调用深度是有限的,超过了栈内存大小,Linux会触发段错误信号:SIGSEGV。JVM应该是捕获了这个信号,并进行了处理。那什么样的处理能支持程序一直运行下去呢?如果你理解了刚刚那个栈图你就清晰了,一定是做了栈帧回溯。

最终结论是:JVM捕获了段错误信号并做了处理,处理方式是栈帧回溯。接下来我只贴核心代码,有能力研究Hotspot源码的可以去自行研究。当然,我的结论不一定就是百分百正确的,如果你有不一样的结论并完成了论证,欢迎找我交流。

这里面还有个知识点我跳过了,我提一下,感兴趣的自己去研究:yellow zone、red zone、glibc guard

 

JVM捕获了异常,并为此创建了执行流

暴力破解美团最新JVM面试题:无限执行

 

研究这个执行流一直往后面追,最终会追到这里

暴力破解美团最新JVM面试题:无限执行

 

之前说的1024是怎么来的,就是MaxJavaStackTraceDepth的值。JVM默认支持的栈最大深度就是1024。为什么是1024,因为触发异常的时候需要遍历栈,导出栈信息,如果栈的深度很深,很费时间费性能,就取了一个有象征意义的值。

 

1024也是一个临界点,当栈深度达到1024,栈帧开始回溯。你可以理解成程序跑起来把栈深度冲到1024,开始回溯,回溯到初始调用时的栈,然后栈深度又开始冲1024,循环往复

暴力破解美团最新JVM面试题:无限执行

 

解释执行时是这样干的,那JIT编译又做了哪些优化呢?

05

最终探索

针对回调做优化,目前主流的优化方式有:尾递归优化、内联优化。JVM没有用尾递归优化,而是用的内联优化,专业名词叫递归内联。

此结论来自之前看的R大的某篇文章。本来想找到贴出来的,没找着。有贴心的小伙伴找着了可以发给我,我贴出来。

到这里,这个问题就探索得无比清晰了。撒花~

作者:五角钱的程序员

原文链接:
https://mp.weixin.qq.com/s/BKq6dbkUbKtVEFhQDyK5ag



Tags:JVM面试题   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
40道JVM面试题!
1、垃圾回收有哪些垃圾收集算法?在JVM(Java虚拟机)中,垃圾回收主要使用了以下几种算法:1、 标记-清除算法(Mark-Sweep):这是最基本的垃圾回收算法。它分为两个阶段:标记阶段和清除阶...【详细内容】
2023-07-26  Search: JVM面试题  点击:(235)  评论:(0)  加入收藏
暴力破解美团最新JVM面试题:无限执行
昨天Java圈,美团曝出了一道变态级面试题:为什么栈溢出后线程没有崩溃?为什么这段代码会永远执行下去? 我的几个交流群、VIP群,争论不休,看大家都是在Java层找答案。很明显,这个问题...【详细内容】
2022-03-16  Search: JVM面试题  点击:(400)  评论:(0)  加入收藏
▌简易百科推荐
Meta如何将缓存一致性提高到99.99999999%
介绍缓存是一种强大的技术,广泛应用于计算机系统的各个方面,从硬件缓存到操作系统、网络浏览器,尤其是后端开发。对于Meta这样的公司来说,缓存尤为重要,因为它有助于减少延迟、扩...【详细内容】
2024-04-15    dbaplus社群  Tags:Meta   点击:(1)  评论:(0)  加入收藏
SELECT COUNT(*) 会造成全表扫描?回去等通知吧
前言SELECT COUNT(*)会不会导致全表扫描引起慢查询呢?SELECT COUNT(*) FROM SomeTable网上有一种说法,针对无 where_clause 的 COUNT(*),MySQL 是有优化的,优化器会选择成本最小...【详细内容】
2024-04-11  dbaplus社群    Tags:SELECT   点击:(0)  评论:(0)  加入收藏
10年架构师感悟:从问题出发,而非技术
这些感悟并非来自于具体的技术实现,而是关于我在架构设计和实施过程中所体会到的一些软性经验和领悟。我希望通过这些分享,能够激发大家对于架构设计和技术实践的思考,帮助大家...【详细内容】
2024-04-11  dbaplus社群    Tags:架构师   点击:(0)  评论:(0)  加入收藏
Netflix 是如何管理 2.38 亿会员的
作者 | Surabhi Diwan译者 | 明知山策划 | TinaNetflix 高级软件工程师 Surabhi Diwan 在 2023 年旧金山 QCon 大会上发表了题为管理 Netflix 的 2.38 亿会员 的演讲。她在...【详细内容】
2024-04-08    InfoQ  Tags:Netflix   点击:(3)  评论:(0)  加入收藏
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(8)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(15)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(11)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(8)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(14)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(10)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条