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

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

 

public class App {
    
    public String getName(String name){
        String res="";
        try {
            res=name;
            return res;
        }finally {
            res="zhangsan";
        }
    }

    public static void main(String[] args) throws InterruptedException {
        App app=new App();
        String name=app.getName("wangwu");
        System.out.println(name);

    }
}

//结果:wangwu

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

 

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

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

 

public java.lang.String getName(java.lang.String);
    descriptor: (Ljava/lang/String;)Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=5, args_size=2
         0: ldc           #2                  // String
         2: astore_2
         3: aload_1
         4: astore_2
         5: aload_2
         6: astore_3
         7: ldc           #3                  // String zhangsan
         9: astore_2
        10: aload_3
        11: areturn
        12: astore        4
        14: ldc           #3                  // String zhangsan
        16: astore_2
        17: aload         4
        19: athrow
      Exception table:
         from    to  target type
             3     7    12   any
            12    14    12   any
      LineNumberTable:
        line 16: 0
        line 18: 3
        line 19: 5
        line 21: 7
        line 19: 10
        line 21: 12
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      20     0  this   Lcom/qlteacher/App;
            0      20     1  name   Ljava/lang/String;
            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

上面这两个个命令就是对应  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 finally语句执行时机深度解析:在return之前还是之后? 在Java中,结构是异常处理的核心语法,用于捕获并响应程序运行时可能出现的异常情况。try块中放置可能抛出异常的代码,catch块负责捕获特定类型的异常并进行处理,而finally块则确保无论是否发生异常,其中的代码都会被执行——这一特性使其成为资源清理的关键位置。try {System.out.println("捕获到除零异常");System.out.println("finally始终执行");该结构的执行流程遵循严格的控制转移规则:即使try或catch中有。 阅读详情

相关推荐

Java中finally块执行与return关系深度剖析

Java finally语句到底是在return之前还是之后执行?Java finally执行深度剖析,具体看这篇博文:http://blog.youkuaiyun.com/lanxuezaipiao/article/details/16922895,这是里面相关的源码,欢迎大家下载使用。

java finally return执行顺序的字节码解读

java finally和return执行顺序的字节码解读 前言 笔者和朋友讨论finally和return的执行顺序问题,笔者毫不犹豫地给出了当然finally在return之前的答案。但是某天朋友发来一个截图,笔者就郁闷了,总觉得哪里不对。截图如下: 如果return总在最后,那返回结果应该是1才对,但现实是残酷的。这不科学,这是笔者当时的内心独白,但直觉...

j_a_d_e的博客 890

AI 编程组合之deepseek+vscode+cline插件,使用deepseek大模型实现代码自动生成

本文介绍了VSCODE下cline插件的安装结合DeepSeek-V3,ai编程的组合套件,举了两个例子一个是生成登录页面,一个是生成贪吃蛇游戏

技术博客 7万+

以字节码角度解释return和finally的执行顺序?

前言(Preface): 关于return和finally的执行顺序,算是一个“老梗”了吧,大家众说纷纭,相信很多人已经看过很多版本的解释。但有些人可能只是通过简单的代码测试得出来的结论,没有从根本上解释这个问题。Java编译器把代码编译成字节码,我们通过反汇编字节码,查看字节码指令顺序,能根本地解释return和finally的执行先后问题。 问题(What): return和fina

落叶无声的专栏 1489

【上海大学计算机组成原理实验报告】五、机器语言程序实验

机器语言程序实验//理解计算机执行程序的实际过程//学习编制机器语言简单程序的方法//将R1中的数值左移n次送OUT,其中n是R2中的数值。(指令码从10开始)//完成R3=R0×R1,结果送OUT。(指令码从30开始)//建立“中文汇编指令”需要哪些条件?//上海大学计算机组成原理实验报告

HackerKevon的博客 2188

Kimi K3大模型API实战:从调用到本地知识库问答系统构建

大语言模型(LLM)作为人工智能的核心技术,通过海量数据训练获得理解和生成自然语言的能力。其工作原理基于Transformer架构,通过自注意力机制捕捉长距离依赖关系。这项技术的核心价值在于能够将非结构化文本转化为可计算、可交互的智能体,极大地提升了信息处理和自动化任务的效率。在应用场景上,大模型广泛应用于智能对话、代码生成、文档总结与问答等领域。其中,国产大模型如月之暗面推出的Kimi K3,凭借其在**长文本处理**和**中文场景优化**方面的优势,为开发者提供了新的技术选项。本文将以Kimi K3为例

weixin_30694389的博客 299

java中finally与return的执行顺序详解

一些准备知识:     首先为了说明白java中finally与return的执行顺序是怎样的这个问题,我们需要做一点准备工作。     java方法是在栈幀中执行,栈幀是线程私有栈的单位,执行方法的线程会为每一个方法分配一小块栈空间来作为该方法执行时的内存空间,栈幀分为三个区域:     1. 操作数栈,用来保存正在执行的表达式中的操作数,数据结构中学习过基于栈的多项式求值算法,操作数栈的

qj19842011的专栏 1万+

Word公式一键转MathType保姆级教程(附omml2mml.xsl报错终极解决方案)

本文提供Word公式一键转MathType的保姆级教程,重点解决常见的omml2mml.xsl报错问题。通过详细分析报错原因、官方解决方案实操步骤及转换后格式优化技巧,帮助用户高效完成公式转换,适用于科研论文和商业文档编辑。

weixin_30082367的博客 555

从字节码的角度来看try-catch-finally和return的执行顺序

从字节码的角度来看try-catch-finally和return的执行顺序全篇以一个例子来说明:先看如下代码:public class ExceptionTest { public void testException(){ try{ //调用一个抛异常的函数 inside_try(); } c

wojiushimogui的博客 2732

ROS2 Nav2实战:解决rviz2显示no map received的3种实用方法(附详细步骤)

本文针对ROS2 Nav2导航栈中rviz2显示“no map received”的常见问题,提供了三种核心解决方案。深入剖析了问题根源在于ROS2生命周期节点管理、QoS策略不匹配及坐标系设置错误,并分别通过手动配置流程、集成生命周期管理器以及调优QoS策略与固化rviz2配置,给出了详细的实战步骤,确保地图数据可靠显示。

j0k1l2m3n的博客 422

几率大的网络安全面试题(含答案)

其他篇章:Java校招极大几率出的面试题(含答案)----汇总 本文面试题汇总: 防范常见的 Web 攻击 重要协议分布层 arp协议的工作原理 rip协议是什么?rip的工作原理 什么是RARP?工作原理 OSPF协议?OSPF的工作原理 TCP与UDP区别总结 什么是三次握手四次挥手? tcp为什么要三次握手? dns是什么?dns的工作原理 一次完整的HTTP请求过程 Cookies和ses...

睶 6万+

《深入理解Java虚拟机》 JAVA 字节码指令 基础

然后调用bispush,将6压到栈顶…iconst 表示加载一个常量,常量的值范围在 -1 ~5 之间,bipush 加载一个字节所能表示的int值,sipush加载两个字节所能表示的int值,ldc 则能加载任意值。Java 虚拟机将局部变量区当成一个数组,如果是实例方法,那么局部变量表这个数组的0号下标位置就是就是this指针,1号下标位置就是 参数,后面依次存放局部变量。因为调用的是实例方法,所以本地变量表序号0的位置上是 this指针,1号上是 方法参数 i,后面依次是方法从上往下的局部变量。

纸上得来终觉浅,绝知此事要躬行 1172

华为OD机试 - 城市聚集度(Python/JS/C/C++ 2025 A卷 200分)

华为OD机试 2025A卷题库疯狂收录中,刷题。

学Java,找哪吒 1131

Java中return和finally到底哪个先执行

本文从基础到高级再到实战,由浅入深,把MySQL讲的清清楚楚,明明白白,这应该是我目前为止看到过最好的有关MySQL的学习笔记了,我相信如果你把这份笔记认真看完后,无论是工作中碰到的问题还是被面试官问到的问题都能迎刃而解!MySQL50道高频面试题整理:《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!面试题整理:**[外链图片转存中…(img-Su9ihOiN-1713125207554)]

2401_84048542的博客 745

五种音频器件综合对比——《器件手册--音频器件》

音频器件当在蜂鸣片的两片电极之间接通交流音频信号时,蜂鸣片会根据信号的大小和频率发生振动,从而产生相应的声音。结构简单、造价低廉。广泛应用于玩具、电子表、电子仪器、电子钟表、定时器等电子电器方面。蜂鸣器是一种一体化结构的电子讯响器,采用直流电源供电,广泛应用于各种电子产品中作发声器件有源蜂鸣器:内部带震荡源,通电即发声,程序控制方便。无源蜂鸣器:内部不带震荡源,需用方波驱动,声音频率可控,价格相对便宜。计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品。

XU157303764的博客 1535

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

finally和return的执行顺序,从根本上理解

网上遍布了finally和return的执行顺序问题,也是困扰新手的问题,一堆分析,各种情况。 其实没有必要那么复杂。 finally实际上就是,java在将代码编译成字节码的时候,在所有分支的可能性路径里面都复制了一份finally块里面的代码。如果finanlly里面有renturn,那么 整个字节码里面,有且只会有一个return, 那就是finanlly里面的renturn 看下如下代码,...

hello world 1350

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Java finally与return执行顺序详解及面试重点

在Java异常处理机制中,finally块与return语句的执行顺序是理解JVM方法调用栈的关键概念。从字节码层面看,JVM会先将return值压入操作数栈,再执行finally代码,最后返回栈顶值。这种机制确保了资源清理的可靠性,但也可能因返回值被修改导致隐蔽的bug。在数据库连接、文件IO等需要资源释放的场景中,正确理解finally的执行时机尤为重要。根据统计,finally与return相关问题出现在62%的Java开发面试中,涉及字节码指令、局部变量表操作等底层原理。掌握这些知识点不仅能避免线上

weixin_33851604的博客 508

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

关于Java中try finally return语句的执行顺序分析

问题分析 finally语句块一定会执行吗? 可能很多人第一反应是肯定要执行的,但仔细一想,如果一定会执行的话 也就不会这么SB的问了。 Demo1 public class Test { public static void main(String[] args) { System.out.println("return value of test(): " +

itmyhome的专栏 4630

JAVA中return与finally的先后关系

以前一直觉得有这个问题存在但也没有深究,今天来彻底探讨一下二者之间的关系预备知识首先是关于return返回的底层知识  java方法是在栈幀中执行,栈幀是线程私有栈的单位,执行方法的线程会为每一个方法分配一小块栈空间来作为该方法执行时的内存空间,栈幀分为三个区域:    1. 操作数栈,用来保存正在执行的表达式中的操作数,数据结构中学习过基于栈的多项式求值算法,操作数栈的作用和这个一样    2....

sinat_22594643的博客 1万+

Java异常处理中finally与return的执行顺序解析

在Java异常处理机制中,finally块用于确保资源释放或清理操作必定执行,这是构建健壮应用程序的基础。其核心原理是JVM会在方法返回前强制执行finally代码块,无论try或catch块中是否存在return语句或抛出异常。这种设计模式特别适用于数据库连接管理、文件IO操作等需要确定性释放资源的场景。通过理解finally与return的交互规则,开发者可以避免常见的资源泄漏问题,特别是在处理基本类型与引用类型返回值时的差异尤为关键。现代Java开发中,结合try-with-resources语法能更

weixin_34344403的博客 397

Java异常机制之try catch finally return执行顺序

Java异常机制之try catch finally return执行顺序Backdround什么时候不执行finallyfinal执行的终极原则没有异常finally也要跑return或throw前finally执行返回值与finally的不解之谜finally里没有return时finally里有return时 Backdround 实验室的大师姐突然问窝很详细的Java异常代码块的执行顺序,...

见不着太阳的蘑菇的博客 958

Java finally执行顺序与return覆盖原理深度解析

try-catch-finally 是程序控制流中保障资源释放与状态清理的核心机制,其本质并非语法糖,而是由JVM字节码强制调度的三段式执行协议。它通过在所有出口路径后插入finally字节码,确保清理逻辑不可绕过;而return语句的实际生效被延迟至finally执行完毕,导致try/catch中的返回值可能被finally中的return覆盖。这一机制支撑着数据库连接关闭、HTTP响应体释放、事务回滚等关键场景的可靠性。深入理解执行顺序与返回值快照行为,是避免异常吞没、连接泄露和语义错乱的技术基石。

weixin_33937778的博客 362

【Java学习】理解try{ return } finally {} 中执行顺序

先看一段代码: public class testFinally { public int test() { int x = 1; try{ return ++x; }catch(Exception e){ }finally{ ++x; } retur

店小不二的博客 1013
上一篇: 将博客搬至csdn
NotAfraid_ZQ
博客等级 码龄12年 1粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值