阿里小哥带你玩转JVM:揭秘try-catch-finally在JVM底层都干了些啥?
让我们准备一个函数:
然后,反编译他的字节码:
首先我们介绍异常表:在编译生成的字节码中,每个方法都附带一个异常表。
异常表中的每一个条目代表一个异常处理器,并且由 from 指针、to 指针、target 指针以及所捕获的异常类型构成。这些指针的值是字节码索引用以定位字节码。
下图就是我特别指出的JVM字节码中的异常表部分。
我们来分析一下这几个语句的执行流程,首先执行:
这相当于执行:
再来:
上图相当于执行
有人问:try去哪了?
我马上就要介绍。此时idiv执行完就有异常了,有异常了先找异常表。
我再贴一下异常表,他是怎么搜索的呢?
当程序触发异常时,Java 虚拟机会从上至下遍历异常表中的所有条目。
当触发异常的字节码的索引值在某个异常表条目的监控范围内,Java 虚拟机会判断所抛出的异常和该条目想要捕获的异常是否匹配。
如果匹配,Java 虚拟机会将控制流转移至该条目 target 指针指向的字节码。
我们看 ,是第四个索引指向的字节码出了问题,显然,此时应该匹配红线这一条记录,从而跳转到第14个索引的字节码。
我们看他怎么做的?
new出一个RuntimeException并抛出,它就是
这一句,按照我们刚才的流程,此时依然需要找到这个RuntimeException在哪个异常表的条目中
此时匹配到异常表的条目,跳转到字节码索引23
继续抛出RuntimeExcpetion,可以注意到 这实际上对应了
这个语句,于是我们可以知道,在三个都出现异常的情况下,实际上最终向外抛出的异常是finally里面的异常。
可以看到当31索引处调用athrow语句抛出异常时,此时异常表没有任何一个条目能够匹配该异常,此时怎么办呢?
如果遍历完所有异常表条目,Java 虚拟机仍未匹配到异常处理器,那么它会弹出当前方法对应的 Java 栈帧,并且在调用者中重复上述操作。
在最坏情况下,Java 虚拟机需要遍历当前线程 Java 栈上所有方法的异常表。
事实上分析以上的整体的全部语句你可以发现,jvm层面有真正的finally吗?
没有
现在的做法是,复制 finally 代码块的内容,分别放在 try-catch 代码块所有正常执行路径以及异常执行路径的出口中。无论是否出现异常,确保一定会执行finally语句。
刚才catch出了异常,依然执行finally语句就可以发现这一点。至于其他路径,大家可以自行验证。我就在这里抛砖引玉了。
至于为什么2-6发生任何异常都跳转到23?大家可以自己想一下这个问题。
我就提示一点 2-6 target为14的条目代表的catch是不能捕获所有异常的,但是你要确保finally的语句能够执行。而2-6恰巧是try语句块的内容。23这个索引恰巧是finally语句的一份复制。
阿里小哥带你玩转JVM:揭秘try-catch-finally在JVM底层都干了些啥?的更多相关文章
- MySQL如何创建一个好索引?创建索引的5条建议【宇哥带你玩转MySQL 索引篇(三)】
MySQL如何创建一个好索引?创建索引的5条建议 过滤效率高的放前面 对于一个多列索引,它的存储顺序是先按第一列进行比较,然后是第二列,第三列...这样.查询时,如果第一列能够排除的越多,那么后面列需 ...
- 【祥哥带你玩HoloLens开发】了解如何实现远程主机为HoloLens实时渲染
今天有一个兄弟在群里讲到他们的项目模型比较大,单用HoloLens运行设备的性能无法满足需要,问道如何将渲染工作交给服务器来做,讲渲染结果传给HoloLens.正好刚刚看官方github的时候发现一个 ...
- 【宇哥带你玩转MySQL】索引篇(一)索引揭秘,看他是如何让你的查询性能指数提升的
场景复现,一个索引提高600倍查询速度? 首先准备一张books表 create table books( id int not null primary key auto_increment, na ...
- 为什么MySQL要用B+树?聊聊B+树与硬盘的前世今生【宇哥带你玩转MySQL 索引篇(二)】
为什么MySQL要用B+树?聊聊B+树与硬盘的前世今生 在上一节,我们聊到数据库为了让我们的查询加速,通过索引方式对数据进行冗余并排序,这样我们在使用时就可以在排好序的数据里进行快速的二分查找,使得查 ...
- 一文带你读懂!华为云在ACMUG技术沙龙上都透露了些啥?
摘要:近日,华为云数据库业务总裁苏光牛在ACMUG中国MySQL用户组主办的 "华为云专场" 技术沙龙中分享了华为云数据库重磅新品GaussDB的核心能力与竞争优势.那么, Gau ...
- Java开发不懂Docker,学尽Java也枉然,阿里P8架构师手把手带你玩转Docker实战
转: Java开发不懂Docker,学尽Java也枉然,阿里P8架构师手把手带你玩转Docker实战 Docker简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一 ...
- 老司机带你玩转面试(2):Redis 过期策略以及缓存雪崩、击穿、穿透
前文回顾 建议前一篇文章没看过的同学先看下前面的文章: 「老司机带你玩转面试(1):缓存中间件 Redis 基础知识以及数据持久化」 过期策略 Redis 的过期策略都有哪些? 在聊这个问题之前,一定 ...
- 带你玩转Visual Studio
带你玩转Visual Studio 带你新建一个工程 工程目录下各文件的含义 解决方案与工程 在这之前先了解一个概念:解决方案与工程. 解决方案(Solution):一个大型项目的整体的工作环境: 工 ...
- 来吧!带你玩转 Excel VBA
来吧!带你玩转 Excel VBA 从错失良机到艰辛的DOS征程,从坎坷购机自学路到转机起程,从爱好到事业,他从一个完全不懂电脑的人到VBA高级应用者,一切全是自学…… 我是罗刚君,来自四川的一个小县 ...
随机推荐
- 12.2新特性 使用DBCA duplicate创建物理备用数据库 (Doc ID 2283697.1)
Creating a Physical Standby database using DBCA duplicate (Doc ID 2283697.1) APPLIES TO: Oracle Data ...
- vue_04day 路由初始
目录 vue_04 项目初始: vue 文件构造: vue项目目录结构: 项目入口(main.js): vue项目启动生命周期: 根组件(vue.js): router.js: 创建的页面: 全局样式 ...
- ej3-0开端
开始 编码多年,总有一些最佳实践,Java也是,比如设计模式,比如Effective Java 3 (ej3) . 设计模式先后看过<大话设计模式>,<HeadFirst 设计模式& ...
- JeeSite | 保存信息修改记录封装
前面写过两篇关于“保存信息修改记录”的内容,分别如下: JeeSite | 保存信息修改记录 JeeSite | 保存信息修改记录续 回顾 第一篇文章通过类字段的比较返回一个有字段值不 ...
- C++ 如何用百行代码实现线程安全的并发队列 | concurrent queue or blocking queue implemented in cpp
本文首发于个人博客https://kezunlin.me/post/cabccf5c/,欢迎阅读最新内容! concurrent queue or blocking queue implemented ...
- PHP实现微信提现(企业付款到零钱)
怎么开通企业付款到零钱? 有的商户号的产品中心是没有这个功能的,不过,该功能的pid(product id)是5,只要随便进去某一个产品,在地址栏把pid改为5. 即可进入该功能页面,进行开通,不过要 ...
- 启动jar包并生成日志的linux脚本
启动脚本 nohup java -Xms300m -Xmx300m -jar $1 >log/$2 2>&1 & 使用方式 建立一个.sh结尾的脚本,里面放入此代码. 需要 ...
- Redis实战(一)Redis简介及环境安装(Windows)
提到Redis,大家肯定都听过,并且应该都在项目中或多或少的使用过,也许你觉得Redis用起来挺简单的呀,但如果有人问你下面的几个问题(比如同事或者面试官),你能回答的上来吗? 什么是Redis? R ...
- 通过修改VAD属性破除锁页机制
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 技术学习来源:火哥(QQ:471194425) 注释:因为自己的知 ...
- JS中的call,apply和bind及记忆方式
总结 call().apply()和bind()都是用来改变函数执行时的上下文,可借助它们实现继承:call()和apply()唯一区别是参数不一样,call()是apply()的语法糖:bind() ...