大家应该都知道,在java中无论是否出异常,finally中的代码都会被执行的,所以我们经常在里面做些释放连接的工作。 但如果有返回值,return与finally是怎么样执行的呢?首先看下面代码。

Java代码  
  1. public class App {
  2. public String getName(String name){
  3. String res="";
  4. try {
  5. res=name;
  6. return res;
  7. }finally {
  8. res="zhangsan";
  9. }
  10. }
  11. public static void main(String[] args) throws InterruptedException {
  12. App app=new App();
  13. String name=app.getName("wangwu");
  14. System.out.println(name);
  15. }
  16. }
  17. //结果:wangwu

下面我们根据生成的字节码来分析下为什么出现这个结果。

首先官网:www.fhadmin.org 进入这个类生成的App.class文件目录,执行命令:javap -c -verbose App

这样就打印出了这个类的字节码信息。下面贴一下我们本次分析需要的内容。

Java代码  
  1. public java.lang.String getName(java.lang.String);
  2. descriptor: (Ljava/lang/String;)Ljava/lang/String;
  3. flags: ACC_PUBLIC
  4. Code:
  5. stack=1, locals=5, args_size=2
  6. 0: ldc           #2                  // String
  7. 2: astore_2
  8. 3: aload_1
  9. 4: astore_2
  10. 5: aload_2
  11. 6: astore_3
  12. 7: ldc           #3                  // String zhangsan
  13. 9: astore_2
  14. 10: aload_3
  15. 11: areturn
  16. 12: astore        4
  17. 14: ldc           #3                  // String zhangsan
  18. 16: astore_2
  19. 17: aload         4
  20. 19: athrow
  21. Exception table:
  22. from    to  target type
  23. 3     7    12   any
  24. 12    14    12   any
  25. LineNumberTable:
  26. line 16: 0
  27. line 18: 3
  28. line 19: 5
  29. line 21: 7
  30. line 19: 10
  31. line 21: 12
  32. LocalVariableTable:
  33. Start  Length  Slot  Name   Signature
  34. 0      20     0  this   Lcom/qlteacher/App;
  35. 0      20     1  name   Ljava/lang/String;
  36. 3      17     2   res   Ljava/lang/String;

首先解释下各个命令:

ldc:将int,float或者String类型常量从常量池推送至栈顶。

astore:将栈顶引用型类型数据存入指定本地变量。

aload:将制定的引用类型变量推送至栈顶

方法的简要执行:

在jvm中,每个线程都具有自己的虚拟机栈。当执行方法时,如上面的getName,就会创建一个栈帧(存储局部变量表,操作数栈等信息)进入虚拟机栈。每一个方法从调用到执行完毕,就是一个栈帧从虚拟机栈中入栈到出栈的过程。

下面分析下字节码:

首先看这行:

stack=1, locals=5, args_size=2,根据这行提示我们能知道这个方法栈的深度为1,局部变量表里有5个数值,参数大小为2.

但我们这个方法getName(String name)只有一个方法啊,哪来的两个。因为对于实例方法,编译器会默认添加一个参数:this,代表对当前实例的引用。这就是我们能在代码中使用this. 的原因。

0: ldc           #2

2: astore_2

上面这两个个命令就是对应 String res="";

首先ldc命令,将常量池中对应 #2(常量池代码没有贴上来)也就是 "",放入操作数栈。

然后将操作数栈数据出栈,并且存入局部变量表的下标为2的slot中。(为什么存入第三个呢,因为第一个是上面说的this,第二个是方法的参数name)

3: aload_1

4: astore_2

上面这两个官网:www.fhadmin.org 个命令就是对应  res=name;

首先aload_1是将局部变量表中的第二个数值(也就是我们的参数name)取出来放入操作数栈

然后astore_2 将刚才的数出栈并且存入局部变量表的第三个位置,也就是上面res的位置,这样就完成了将name的值赋给了res。

5: aload_2

6: astore_3

代码继续执行,不出异常的话就因该执行return res;这句代码了

当执行到这句代码的时候,首先从局部变量表第三个位置(res变量)取出res的数值放入操作数栈顶。然后出栈放入操作数栈的第四个位置(为了方便,我们暂且给它起个名字为returnValue)。

通过上面命令这个方法需要返回的值就已经确定并存储好了。

7: ldc           #3                  // String zhangsan

9: astore_2

这两句就是finally中的语句了。

首先将常量池对应 #3的常量(zhangsan)压入操作数栈。然后将这个数出栈astore_2并且存入局部变量表的第三个位置(res),这样就完成了res="zhangsanj";需要注意的是此时虽然改了res,但我们上面所存放的returnValue值还未改变

10: aload_3

11: areturn

这两步就是return操作了,将局部变量表中第四个位置的数值(上面的returnValue)压入操作数栈,然后返回。

到这里,这个方法就执行完了。后面的代码是异常分支,当出现异常的时候会走下面的代码,这里不再分析。

总结:

当执行代码碰到return的时候,会将要返回的值存入局部变量表(暂且起名为returnValue)。如果有finally代码块,就会执行finally中的代码,执行完毕后,取出returnValue中的内容,进行反回。

上面代码中res作为返回值,但res变量本身与返回值存放在不同的位置,所以后期改了res后,returnValue未改变,

java中return与finally的执行顺序分析(根据字节码分析)相关推荐

  1. java 静态块初始化_简单了解java中静态初始化块的执行顺序

    这篇文章主要介绍了简单了解java中静态初始化块的执行顺序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在java中,其应该是先于所有的方法执行. ...

  2. java中子类继承父类程序执行顺序问题

    为什么80%的码农都做不了架构师?>>>    Java中,new一个类的对象,类里面的静态代码块.非静态代码.无参构造方法.有参构造方法.类的一般方法等部分,它们的执行顺序相对来说 ...

  3. java类初始化顺序_「漫画」Java中的父子类的执行顺序到底是怎么一回事?

    ----下课后---- 结论 类的加载顺序. (1) 父类静态代码块(包括静态初始化块,静态属性,但不包括静态方法) (2) 子类静态代码块(包括静态初始化块,静态属性,但不包括静态方法 ) (3) ...

  4. java 中的finally 语句块执行顺序

    2019独角兽企业重金招聘Python工程师标准>>> 参考博文1:https://www.ibm.com/developerworks/cn/java/j-lo-finally/ ...

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

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

  6. JAVA异常中的坑--trytry-catch-finally的执行顺序

    结论: 不管有没有出现异常,finally代码块都会执行: 不管try和catch的代码块中有return时,finally仍会执行,且如果finally代码块也有return,则此代码肯定会返回fi ...

  7. java中demo接人_return的用法_如何理解java中return的用法?

    C语言中return用法?(请熟练者进) return是返回值,这个返回值是和函数的类型有关的,函数的类型是什么,他的返回值就是什么 比方主函数intmain() {}这里就必须有一个return,只 ...

  8. Asp.net 中 OnClientClick 与 OnClick 的执行顺序

    Asp.net 中 OnClientClick 与 OnClick 的执行顺序为:客户端的OnClientClick先执行,服务器端的OnClick后执行. 拓展:在执行完客户端的OnClientCl ...

  9. SQL server中的SELECT查询语句执行顺序

    各位大牛们好第一次写博客有点小激动!以后我会把自己的心得分享给大家,求各种评论 SQL server 中SELSECT查询语句的执行顺序如下: (8) SELECT   (9) DISTINCT (1 ...

  10. oracle and和or的执行顺序,Oraclewhere语句中and,or,not的执行顺序

    Oracle where子句里面的and,or,not:1.a and b(顺序执行) (1)a,b同true则true, (2)a,b一false则false, [1]若a为 Oracle wher ...

最新文章

  1. Android Studio报错解决:droid.tools.idea.welcome.install.WizardException: SDK tools directory is missing
  2. uniapp无法使用substr_关公战秦琼------Excel、SPSS Modler和R的使用对比(下)
  3. Google Authenticator加强ssh安全
  4. 随想录(gcc生成的中间语言、汇编代码)
  5. python人工智能入门优达视频_python入门视频教你搭建机器学习Python环境的正确姿势...
  6. python判断丑数_LeetCode-python 264.丑数 II
  7. CDN设置回源host的意义
  8. ps关于计算机logo设计,做LOGO运用ps界面技巧
  9. 大学生数学建模赛题解析及优秀论文-2021电工杯A题高铁牵引供电系统运行数据分析及等值建模(附Python代码)
  10. Android ORC文字识别之识别身份证号等(附源码)
  11. 用 Python 制作“会跳舞”的动态图表
  12. 计算机的使用方法说明书,使用说明
  13. 常用时序数据地址 MTGNN
  14. 特斯拉神器TeslaMate一键安装,终于来了
  15. 字典的添加、更新、修改
  16. 地理信息系统(GIS)系列——绪论
  17. 玉米社:抖音账号被限流了怎么办?一步步教你解除限制
  18. Pyinstaller打包pygame包的aliens.py文件
  19. java.lang.NoSuchMethodError:scala.collection.immutable.HashSet$.empty()Lscala/collection/
  20. 卫星定位与导航相关知识的整理

热门文章

  1. win7 计算机定时关机脚本,win7怎么定时关机?win7定时关机设置两种方法
  2. python多元回归因子选取_用Python进行多元线性回归分析(附代码)
  3. (2015秋) 团队博客及分组情况
  4. 软件工程——软科中国大学专业排名
  5. 计算机组成原理SRop,【9A文】计算机组成原理历年真题.docx
  6. 卡饭论坛--金山毒霸/卫士 广告过滤规则(附纯文本版) [2015.7.1] 党生日版
  7. EMC被唯冠科技诉侵权:商标纠纷延宕13年
  8. android路由器安装wifidog,Wifidog-刷OpenWRT标准版固件后安装LuCI的方法
  9. 字幕/打轴/压制小tip——Aegisub MeGUI 极简操作指南
  10. 对学校的希望和寄语_对小学生的寄语与希望