直接进入主题。看如下代码:

public int test(){int i=0;try {i=1;return i;} catch (Exception e) {i=2;return i;}finally{i=3;}
}

相信有点经验的程序员一眼就能说出返回的结果为1,但是您真的知道返回的结果为什么为1吗?下面我们通过分析下当前方法的字节码,来说明为什么。

查看字节码命令:javap -verbose class文件

知识点简单概要:
看如下字节码需要简单了解下栈的结构。
栈包括:局部变量表、操作数栈、动态连接、方法出口等。
下面字节码主要是对操作栈和局变量表的操作。

test方法的字节码如下:

 stack=1, locals=5, args_size=10: iconst_0                 将常量0压入到操作栈顶1: istore_1                  将栈顶元素0存储到局部变量表中的第二个slot中  (slot2=0)  i=02: iconst_1                 将常量1压入到操作栈顶3: istore_1                  将栈顶元素1存储到局部变量表中的第二个slot中  (slot2=1)  i=14: iload_1                   将局部变量中第二个变量 (i=1) 压入到操作栈顶5: istore        4            将栈顶元素1存储到局部变量表中的第四个slot中  (slot4=1) 7: iconst_3                 将常量3压入到操作栈顶8: istore_1                  将栈顶元素3存储到局部变量表中的第二个slot中  (slot2=1)  i=39: iload         4            将局部变量中第四个变量 (slot4=1) 压入到操作栈顶11: ireturn                   返回操作栈顶值,这时操作栈中栈顶值为1。12: astore_2               将栈顶元素(e)存储到局部变量表的第三个slot中13: iconst_2                将常量2压入到操作栈顶14: istore_1                 将栈顶元素2存储到局部变量表中的第二个slot中  (slot2=2)  i=215: iload_1                  将局部变量中第二个变量 (i=2) 压入到操作栈顶16: istore        4           将栈顶元素2存储到局部变量表中的第四个slot中  (slot4=2) 18: iconst_3                将常量3压入到操作栈顶19: istore_1                 将栈顶元素3存储到局部变量表中的第二个slot中  (slot2=1)  i=320: iload         4           将局部变量中第四个变量 (slot4=2) 压入到操作栈顶22: ireturn                   返回操作栈顶值,这时操作栈中栈顶值为2。23: astore_3               将栈顶元素(其它异常,Exception之外的)存储到局部变量表的第四个slot中24: iconst_3                将常量3压入到操作栈顶25: istore_1                将栈顶元素3存储到局部变量表中的第二个slot中  (slot2=3)  i=326: aload_3                将局部变量中第四个变量 (其它异常) 压入到操作栈顶27: athrow                  抛出栈顶元素(异常信息) 无返回值

stack=1, locals=5, args_size=1
- stack=1:操作栈的深度
- locals=5:局部变量表中5个slot(槽位),每个slot存储能一个变量(long、double 需要两个slot存储)
1. this变量
2. i 变量
3. e 变量(Exception)
4. Exception之外异常的变量
5. 临时存储变量(返回值从临时存储中返回的)
- args_size=1: 方法的参数个数(该方法无参数,为什么这里args_size为1呢?因为这个是实例方法,不是静态方法,他默认会传过来当前实例的引用,也就是this变量)

字节码执行路径

通过字节码我们发现在编译成class文件的时候,已经把三种执行路径都写到class文件中了。
1. 第一种路径
第【1-11】行,程序正常执行顺序(无异常)
2. 第二种路径
第【12-22】行,程序报Exception的异常
3. 第三种路径
第【23-27】行,程序报Exception之外的异常

字节码大白话解释说明

第[0-1]行,代码:int i=0;
第[2-3]行,try块中代码:i=1;
第[4-5]行,遇到return时,把 i 的值临时存储起来,然后执行finally中的代码。
第[7-8] 行,finally块代码:i=3
第[9-11] 行,执行return语句,把临时存储的 i 值返回。(执行finally代码对返回值无影响)
第[12]行,catch块代码: (Exception e)
第[13-14]行,catch块代码:  i=2
第[15-16]行,遇到catch块中的return时,把 i 的值临时存储起来,然后执行finally中的代码。
第[18-19]行,finally块代码:i=3
第[20-22]行,执行catch块中return语句,把临时存储的 i 值返回。(执行finally代码对返回值无影响)
第[23]行,局部变量表中存储Exception之外的异常
第[24-25]行,finally块代码:i=3
第[26-27]行,将Exception之外的异常压入栈顶,并抛出(无返回值)

结论

通过字节码,我们发现,在try语句的return块中,return 返回的变量并不是直接返回 i 值,而是在执行finally块之前把i值存储在临时区域,当执行return时直接返回的临时区域中的值,即使在finally语句中把变量 i 的值修改了,也不会影响返回的值。

本人简书blog地址:http://www.jianshu.com/u/1f0067e24ff8    
点击这里快速进入简书

字节码分析finally块对return返回值的影响相关推荐

  1. python把桢写入txt_Java 字节码与字节码分析

    1.1 Java 字节码简介Java 字节码由单字节(byte)的指令组成,理论上最多支持 256 个操作码(opcode).实际上 Java 只使用了200左右的操作码, 还有一些操作码则保留给调试 ...

  2. java中类的字节码_Java 字节码与字节码分析

    1.1 Java 字节码简介Java 字节码由单字节(byte)的指令组成,理论上最多支持 256 个操作码(opcode).实际上 Java 只使用了200左右的操作码, 还有一些操作码则保留给调试 ...

  3. Android Kotlin 学习总结(一) 《KAE 优缺点并且深入字节码分析工作原理》

    本章会分为以下内容: 1.Kotlin KAE介绍,使用和原始Android findViewById对比优缺点 2.Kotlin KAE所存在的问题 3.通过字节码分析他的实现原理 阅读本章内容大概 ...

  4. 可以在finally代码块中处理返回值么?

    先来看一段代码: public boolean doSomething() {try {// do something} finally {// ...return true;} } 这段代码的fin ...

  5. java中return返回值_Java中return的用法

    展开全部 一.return语句总是用在方法中,有两个作用. 一个是返回方法指定类型的值(这个值总62616964757a686964616fe59b9ee7ad9431333366306434是确定的 ...

  6. python基础 python函数 函数概念 函数的多种参数 多种调用参数 装包 解包 函数代码块 函数的返回值

    python基础 python函数 函数概念 函数的多种参数 多种调用参数 装包 解包 函数代码块 函数的返回值 一 .函数概念 函数是根据需要,将代码打包为代码块, 每一个代码块就可以封装为一个函数 ...

  7. R语言return返回值的形式实战

    R语言return返回值的形式实战 目录 R语言return返回值的形式实战 #包含return的R函数 #不包含return的R函数

  8. return 返回值的问题

    def yue(): print("1. 打开手机") print("2. 打开陌陌") print("3. 找个漂亮的小姐姐") prin ...

  9. C#获取存储过程的 Return返回值和Output输出参数值

    一.不用SQLHelper.cs等帮助类 1.获取Return返回值  程序代码  存储过程 Create PROCEDURE MYSQL   @a int,   @b int AS   return ...

最新文章

  1. spring boot构建基础版web项目(一)springboot、thymeleaf控制层基础构
  2. 我的微信luogantt
  3. JSjQuery全选反选父项子项联动多选框
  4. linux 性能监视命令
  5. windowbuilder点击按钮出现新界面_掌握这几招,轻松设计出高点击率的行为召唤按钮...
  6. iis启动服务时提示在本地计算机 无法启动iis admin服务,无法启动IIS Express Web服务器...
  7. 安徽省滁州市谷歌卫星地图下载
  8. iphone se卡贴教程
  9. SMBMS项目(一)
  10. VScode光标乱跳、换行失灵、保存导致光标乱跳等解决办法
  11. python计算圆周率_用python程序求圆周率到任意位
  12. 人工智能畅想ps海报教程_如何战胜鲁班人工智能做图?大战鲁班海报制作教程【PS教程】...
  13. ApacheCN 公众号文章汇总 2019.9
  14. 【学习笔记】《卓有成效的管理者》 第二章 掌握自己的时间
  15. android系统如何获得外置卡路径
  16. HDU 4833 Best Financing 一脸费用流的dp
  17. 如何使用 ffmpeg替代方式将webm转换为常用mp3格式
  18. Netty学习笔记:二、NIO网络应用实例-群聊系统
  19. eprint自定义打印工具
  20. 查看GPU和GPU驱动版本+GPU驱动版本更新

热门文章

  1. 四十一、深入Java中的 File类
  2. 机器学习著名定理之—No Free Lunch定理详解
  3. ACM旗舰期刊最新综述:一览端到端人脸识别最新进展
  4. 直播 | AAAI 2022论文解读:三⻆分解一致性约束的端到端语音翻译
  5. Transformer落地:使用话语重写器改进多轮人机对话
  6. AI 玩微信跳一跳的正确姿势:跳一跳 Auto-Jump 算法详解
  7. java处理最后一周_Java获取某年某周的最后一天
  8. python画日漫_不能错过的Python漫画
  9. 华为手机连电脑_华为手机微信聊天记录如何导出电脑的四大方法
  10. 【Java代码】反射机制处理传递给mapper文件的非Map类型参数对象(指定属性为空则设置默认值)