java异常捕获分析

硅谷探秘者 4594 0 0

java异常捕获分析

    思考问题:

    调用下面的方法分别会返和输出回什么?

package com.itdragon.controller;

import org.junit.Test;

public class TestMain {
	public int test1() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			System.out.println("test1:err");
			a=100;
			return a;
		}finally {
			System.out.println("test1:fin");
			a=200;
			return a;
		}
	}
	public int test2() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			System.out.println("test2:err");
			a=100;
			return a;
		}finally {
			System.out.println("test2:fin");
			a=200;
		}
		return a;
	}
	
	@Test
	public void tests(){
		System.out.println("test1:"+test1());
		System.out.println();
		System.out.println("test2:"+test2());
	}
	
}	

QQ截图20190511202802.png

    众所周知,java捕获到异常时,先执行catch 代码块,如果有finally代码块,那么无论最后有没有异常都会执行finally代码块。

    对于test1都好理解,最后在finally中返回,值为200.

    但是对于test2就有点难以理解,认为应该返回200,但是却返回了100.


    对于上述两个方法简化,在做叙述:

public int test1() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			a=100;
			return a;
		}finally {
			a=200;
			return a;
		}
	}
	public int test2() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			a=100;
			return a;
		}finally {
			a=200;
		}
		return a;
	}

    

反编译出的字节码如下:

test1

public int test1();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=1
         0: iconst_0	//将int型0推送至栈顶  
         1: istore_1	//将栈顶int型数值存入第二个本地变量  
         2: iconst_1	//将int型1推送至栈顶 
         3: iconst_0	//将int型0推送至栈顶  
         4: idiv		//将栈顶两int型数值相除并将结果压入栈顶  
         5: istore_1	//将栈顶int型数值存入第二个本地变量  
         6: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
         9: istore_1	//将栈顶int型数值存入第二个本地变量  
        10: iload_1		//将第二个int型本地变量推送至栈顶 
        11: ireturn		//从当前方法返回int  
        12: astore_2	//将栈顶引用型数值存入第三个本地变量
        13: bipush        100	//将单字节的常量值(-128~127)推送至栈顶
        15: istore_1	//将栈顶int型数值存入第二个本地变量  
        16: iload_1		//将第二个int型本地变量推送至栈顶 
        17: istore_3	//将栈顶int型数值存入第四个本地变量
        18: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
        21: istore_1	//将栈顶int型数值存入第二个本地变量
        22: iload_1		//将第二个int型本地变量推送至栈顶 
        23: ireturn		//从当前方法返回int  
        24: astore        4		//将栈顶引用型数值存入指定本地变量
        26: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
        29: istore_1	//将栈顶int型数值存入第二个本地变量
        30: iload_1		//将第二个int型本地变量推送至栈顶 
        31: ireturn		//从当前方法返回int  
      Exception table:
         from    to  target type
             2     6    12   Class java/lang/Exception
             2     6    24   any
            12    18    24   any
            24    26    24   any

test2:

 public int test1();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=1
         0: iconst_0	//将int型0推送至栈顶
         1: istore_1	//将栈顶int型数值存入第二个本地变量	
         2: iconst_1	//将int型1推送至栈顶
         3: iconst_0	//将int型0推送至栈顶
         4: idiv		//将栈顶两int型数值相除并将结果压入栈顶
         5: istore_1	//将栈顶int型数值存入第二个本地变量
         6: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
         9: istore_1	//将栈顶int型数值存入第二个本地变量
        10: goto          34	//无条件跳转
        13: astore_2	////将栈顶引用型数值存入第三个本地变量
        14: bipush        100	//将单字节的常量值(-128~127)推送至栈顶
        16: istore_1	// 将栈顶int型数值存入第二个本地变量
        17: iload_1		//将第二个int型本地变量推送至栈顶
        18: istore_3	//将栈顶int型数值存入第四个本地变量
        19: sipush        200	// 将一个短整型常量值(-32768~32767)推送至栈顶  
        22: istore_1	//将栈顶int型数值存入第二个本地变量 
        23: iload_3		//将第四个int型本地变量推送至栈顶
        24: ireturn		// 从当前方法返回int
        25: astore        4		//将栈顶引用型数值存入指定本地变量
        27: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶  
        30: istore_1	//将栈顶int型数值存入第二个本地变量
        31: aload         4	//将指定的引用类型本地变量推送至栈顶 
        33: athrow		//将栈顶的异常抛出
        34: iload_1		//将第二个int型本地变量推送至栈顶
        35: ireturn		// 从当前方法返回int
      Exception table:
         from    to  target type
             2     6    13   Class java/lang/Exception
             2     6    25   any
            13    19    25   any
            25    27    25   any

        可能对于不是太了解字节码的同学来说不好理解。

        但是从中我的理解是:当有finally块存在的时候,虚拟机执行完catch块中的代码时不会立即返回,而是把return语句给屏蔽了,将catch中的代码执行完以、变量在局部变量表中保存好以后,继续执行finally块中的代码,如果finally块中有返回语句,则直接返回,否则,虚拟机去取在catch块中保存的局部变量,放入栈顶,返回。



评论区
请写下您的评论...
暂无评论...
猜你喜欢
java基础 2346 Java体系java体系继承图ThrowableThrowable类是所有的父类,见的子类有两个Error、Exception。ErrorError类就是程序运行时候抛出的最严重级别的
java基础 3751 当前线程所执行的字节码的行号指示器。在Java虚拟机的概念模型里[1],字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,它是程序控制流的指示器,支、循环、跳转、处理
official 878 《深入理解java虚拟机》[TOC]一、运行时数据区域  Java虚拟机在执行Java程序的过程中会把它所管理的内存划为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有的区域随
official 917 《操作系统》中断机制的诞生早期的计算机各程序只能串行执行,执行完这一个才能执行下一个,所以系统资源利用率低。为了解决上述问题,人们发明了操作系统(作为计算机的管理者),引入中断机制,实现了多道程序并发执行本质:发生中断就意味着需要操作系统介入,开展管理工作。中断的概念和作用1.当中断发生时,CPU立即进入核心态2.当中断发生后,当前运行的进程暂停运行,并由操作系统内核对中断进行处理3.对于不同的中
spring/springmvc 2342 springmvc统一返回信息当服务器代码为: @RequestMapping("/res") publicMyAjaxResultres(@RequestParam(name
java基础 1377 1.HashMap的构造函数1.publicHashMap()publicHashMap(){this.loadFactor=DEFAULT_LOAD_FACTOR;//allotherfieldsdefaulted}构造一个空的HashMap,初始容量为16,负载因子为0.75,负载因子和它的作用将会在下方解释。2.publicHashMap(intinitialCapacity)publicH
java虚拟机(jvm) 4453 Java对象的创建Java是一门面向对象的编程语言,在Java程序运行过程中无时无刻都有对象被创建出来。在语言层面上,创建对象(例如克隆、反序列化)通仅仅是一个new关键字而已,而在虚拟机中,对象
java虚拟机(jvm) 3026 jvm内存模型(1)Java虚拟机在执行Java程序的过程中会把它所管理的内存划为若干个不同的数据区域jvm包括三大子系统:类加载子系统,运行时数据区(内存结构),执行引擎详细图示
归档
2018-11  12 2018-12  33 2019-01  28 2019-02  28 2019-03  32 2019-04  27 2019-05  33 2019-06  6 2019-07  12 2019-08  12 2019-09  21 2019-10  8 2019-11  15 2019-12  25 2020-01  9 2020-02  5 2020-03  16 2020-04  4 2020-06  1 2020-07  7 2020-08  13 2020-09  9 2020-10  5 2020-12  3 2021-01  1 2021-02  5 2021-03  7 2021-04  4 2021-05  4 2021-06  1 2021-07  7 2021-08  2 2021-09  8 2021-10  9 2021-11  16 2021-12  14 2022-01  7 2022-05  1 2022-08  3 2022-09  2 2022-10  2 2022-12  5 2023-01  3 2023-02  1 2023-03  4 2023-04  2 2023-06  3 2023-07  4 2023-08  1 2023-10  1 2024-02  1 2024-03  1 2024-04  1 2024-08  1
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础 xxl-job rabbitmq haproxy srs 音视频 webrtc javascript 加密算法
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。