java-基础-【三】try/catch/finally
原文地址:
https://my.oschina.net/bieber/blog/703251
一、单层的try/catch
- public int test(int a,int b){
- try{
- return a+b;
- }catch (Exception e){
- throw new CustomException();
- }
- }
通过javap -v查看JVM编译成class字节码之后是如何处理这个try/catch
的
- public int test(int, int);
- flags: ACC_PUBLIC
- Code:
- stack=2, locals=4, args_size=3
- 0: iload_1 // 将第一个int参数压入队列(第一个入参)
- 1: iload_2 // 将第二个int参数压入队列(第二个入参)
- 2: iadd //弹出队列中第一个和第二个参数执行相加,并把相加结果压入队列
- 3: ireturn //弹出队列第一个元素,并return。
- 4: astore_3 //此处是try开始的逻辑
- 5: new #3 // class com/bieber/demo/CustomException
- 8: dup
- 9: invokespecial #4 // Method com/bieber/demo/CustomException."<init>":()V
- 12: athrow //将队列中的第一个元素弹出,并当做异常抛出,到此整个方法体完毕
- Exception table:
- from to target type
- 0 3 4 Class java/lang/Exception
- LineNumberTable:
- line 13: 0
- line 14: 4
- line 15: 5
- LocalVariableTable:
- Start Length Slot Name Signature
- 5 8 3 e Ljava/lang/Exception;
- 0 13 0 this Lcom/cainiao/cilogisticservice/ExceptionClass;
- 0 13 1 a I
- 0 13 2 b I
- StackMapTable: number_of_entries = 1
- frame_type = 68 /* same_locals_1_stack_item */
- stack = [ class java/lang/Exception ]
上面是test
方法JVM编译之后的结果,上面的Code
块是整个方法体的内容,而从0-3可以视为是方法体的正常逻辑,4-12可以视为try/catch块,从方法体的指令看,正常情况下执行到3
的地方就完毕了,而不会去执行4-12的指令。
那就得出结论,try/catch
代码块在正常逻辑的时候是不会被执行的,于是对于对代码加上try/catch
块,并不会影响代码的执行效率,因为根本不会有多余的指令被执行,只有出现异常的时候才会多出执行异常的指令。
上面的JVM编译的字节码的时候除了Code
代码块,还有Exception table
代码块,从这个代码块的内容可以看到,包含四列(from,to,target,type),其中from
和to
表示这个try/catch
代码块是从哪开始到哪结束,可以看到上面的try/catch
代码块是从Code
代码块的0-3,也就是从加载第一个int值到返回结果的代码块,target
表示这个try/catch
代码块执行逻辑在哪里开始,比如上面的表示从Code
中的4开始,也就是astore_3
指令开始,直到athrow
指令被执行的地方,在Exception table
中的一行还有type
列,表示是这个异常类型,用于在一个try/catch
代码块出现多个catch
内容,用于匹配正确的异常类型。
二、一个try对应多个catch
- public int test(int a,int b){
- try{
- return a+b;
- }catch (Exception e){
- a++;
- throw new CustomException();
- }catch (Throwable t){
- b++;
- throw new CustomException();
- }
- }
JVM对上面代码编译后的结果:
- public int test(int, int);
- flags: ACC_PUBLIC
- Code:
- stack=2, locals=4, args_size=3
- 0: iload_1
- 1: iload_2
- 2: iadd
- 3: ireturn
- 4: astore_3
- 5: iinc 1, 1
- 8: new #3 // class com/bieber/demo/CustomException
- 11: dup
- 12: invokespecial #4 // Method com/bieber/demo/CustomException."<init>":()V
- 15: athrow
- 16: astore_3
- 17: iinc 2, 1
- 20: new #3 // class com/cainiao/cilogisticservice/CustomException
- 23: dup
- 24: invokespecial #4 // Method com/cainiao/cilogisticservice/CustomException."<init>":()V
- 27: athrow
- Exception table:
- from to target type
- 0 3 4 Class java/lang/Exception
- 0 3 16 Class java/lang/Throwable
- LineNumberTable:
- line 13: 0
- line 14: 4
- line 15: 5
- line 16: 8
- line 17: 16
- line 18: 17
- line 19: 20
- LocalVariableTable:
- Start Length Slot Name Signature
- 5 11 3 e Ljava/lang/Exception;
- 17 11 3 t Ljava/lang/Throwable;
- 0 28 0 this Lcom/cainiao/cilogisticservice/ExceptionClass;
- 0 28 1 a I
- 0 28 2 b I
- StackMapTable: number_of_entries = 2
- frame_type = 68 /* same_locals_1_stack_item */
- stack = [ class java/lang/Exception ]
- frame_type = 75 /* same_locals_1_stack_item */
- stack = [ class java/lang/Throwable ]
和上面的内容对比一下会发现,在Code
中多出了一段astore_3/athrow
块,并且在Exception table
中多了一行,想想通过上面的解释,对这个多出的一行的目的应该都知道是用来什么的,由于我在catch
中成了throw
之外,还多了一个++
的操作,可以看到在astore_3/athrow
块中多出了iinc
指令,所以可以理解,try/catch
在JVM中对应的是一个子代码块,在条件满足(出现匹配的catch异常)的时候会被执行。
下面我整理一下当出现异常的(这里说的是有try/catch
的异常)JVM处理流程:
- 1、在try/catch出现异常
- 2、JVM会去`Exception table`查找匹配的异常类型
- 3、假设匹配上了,那么读取from,to,target,获取待执行的`try/catch`块的指令(具体是否抛出,看是否有athrow指令)。
三、try/finally块的执行处理
- public int test(int a,int b){
- try{
- return a+b;
- }catch (Exception e){
- a++;
- throw new CustomException();
- }finally {
- b++;
- }
- }
JVM编译后的指令:
- public int test(int, int);
- flags: ACC_PUBLIC
- Code:
- stack=2, locals=5, args_size=3
- 0: iload_1
- 1: iload_2
- 2: iadd
- 3: istore_3 //将栈顶的元素存储局部变量数组的第三个位置
- 4: iinc 2, 1 //执行b++
- 7: iload_3 //把局部变量第三个位置的数值压入栈顶
- 8: ireturn //弹出栈顶,并且返回
- 9: astore_3
- 10: iinc 1, 1 //a++
- 13: new #3 // class com/bieber/demo/CustomException
- 16: dup
- 17: invokespecial #4 // Method com/bieber/demo/CustomException."<init>":()V
- 20: athrow
- 21: astore 4
- 23: iinc 2, 1 //b++
- 26: aload 4
- 28: athrow
- Exception table:
- from to target type
- 0 4 9 Class java/lang/Exception
- 0 4 21 any
- 9 23 21 any
- LineNumberTable:
- line 13: 0
- line 18: 4
- line 14: 9
- line 15: 10
- line 16: 13
- line 18: 21
- LocalVariableTable:
- Start Length Slot Name Signature
- 10 11 3 e Ljava/lang/Exception;
- 0 29 0 this Lcom/cainiao/cilogisticservice/ExceptionClass;
- 0 29 1 a I
- 0 29 2 b I
- StackMapTable: number_of_entries = 2
- frame_type = 73 /* same_locals_1_stack_item */
- stack = [ class java/lang/Exception ]
- frame_type = 75 /* same_locals_1_stack_item */
- stack = [ class java/lang/Throwable ]
通过上面的代码,你会发现在Exception table
都出了两行,其实我们只是在代码中只有一个try/catch
块,而这里出现了三个,那么另外两个是做什么的呢?可以看到多出的两行的type都是any
,这里的any
表示的是任何异常类型,多出的第一行,是从0-4
,表示0-4
之间的指令出现异常,会从21
的指令开始执行,发现执行的是b++
(finally)的内容,多出的第二行是9-23
,表示9-23
之间的指令被执行的过程中出现异常也会从21
行开始执行(也是执行finally
的内容),而9-23
其实是catch
的代码逻辑。上面均是出现了异常会触发finally
的代码执行,正常情况下会发现4
的位置执行了finally
的内容,然后再执行ireturn
指令,这里可以得出,JVM处理finally
其实是对于正常的指令队列增加了finally
代码块的指令,以及对异常中添加了finally
代码块的指令,这也就导致了fianlly
在任何地方都可以被执行,其实就是冗余了指令队列(其实思想比较简单)。
java-基础-【三】try/catch/finally的更多相关文章
- Java基础系列 - try...catch...finally
package com.test6; import java.io.FileReader; import java.io.IOException; /** * try...catch...finall ...
- Java 基础三、接口与内部类
1. 在Java程序语言中,接口是对类的一种描述.例如Arrays类中sort方法声明可以对对象进行排序,但前提是对象所属的类必须实现Comparable接口. public interface ...
- java基础(三):反射、反序列化破解单列模式和解决方式
单例模式指的是一个类只有一个对象,通过一些措施达到达到这个目的.但是反射和反序列化可以获得多个不同的对象. 先简单的认识一下单例模式 一:单例模式 通过私有构造器,声明一个该类的静态对象成员,提供一个 ...
- java基础(三) 加强型for循环与Iterator
引言 从JDK1.5起,增加了加强型的for循环语法,也被称为 "for-Each 循环".加强型循环在操作数组与集合方面增加了很大的方便性.那么,加强型for循环是怎么解析的 ...
- Java面试题总结之Java基础(三)
1.JAVA 语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try 块中可以抛出异常吗? 答:Java 通过面向对象的方法进行异常处理, ...
- java基础(三)
1.枚举类,使用enum定义的枚举类默认继承java.lang.Enum,而不是Object类.枚举类的所有实例必须在枚举类中显示列出,否则这个枚举类永远都不能产生实例.相关内容较多,需要后续继续跟进 ...
- java 基础三 下雪
通过repaint()方法进行重画. import javax.swing.JFrame; import javax.swing.JPanel; import java.awt.Graphics; p ...
- java基础三种循环的使用及区别
摘要:Java新人初学时自己的一些理解,大神们路过勿喷,有什么说的不对不足的地方希望能给予指点指点,如果觉得可以的话,希望可以点一个赞,嘿嘿,在这里先谢了.在这里我主要说的是初学时用到的Java三个循 ...
- java 基础三
1 运算符 1.1 比较运算符 比较运算符的结果都是boolean类型,也即是要么是true,要么是false. 比较运算符"=="不能写成"=". > ...
- Java基础(三)-final关键字分析
今天来谈谈final关键字的作用, 虽然有很多博文关于final进行了很深的研究,但还是要去记录下谈谈自己的见解加深下印象.下面直接进入主题: 一.final关键字的作用 1.被final修饰的类不能 ...
随机推荐
- jQuery继承extend用法详解
/直接基于jQuery的扩展,判断是否为空 $.isBlank = function(obj){ return(typeof(obj)=='undefined'||obj==''||obj==nu ...
- centos7,yum安装工具报错
1.问题描述:yum安装gcc和其他的工具时一直报错: 2.问题解决: 网上看到有类似文章: No more mirrors to try. 得知这可能是错误的缓存源导致,直接两个命令解决: yum ...
- _T("D:\\122.txt")【字符集问题】或【类型转换问题】
项目->属性->常规->字符集->使用多字节字符集!时用_T("Filename"), 貌似不是字符集的问题! 1.使用替换,,,后, _T(" ...
- Ocx控件注册不成功?可能是tlb文件导致~
Ocx文件是最常用的文件,实际操作中常常需要注册之~ 但是问题来了,经常会出现注册不成功的问题: 解决方法: 1.以“管理员身份”注册 2.Dependency Walker查看依赖是否缺失 3.查看 ...
- day15<集合框架>
集合框架(对象数组的概述和使用) 集合框架(集合的由来及集合继承体系图) 集合框架(Collection集合的基本功能测试) 集合框架(集合的遍历之集合转数组遍历) 集合框架(Collection集合 ...
- swift - 各种手势用法大全
UIGestureRecognizer有许多子类,用于监听一些常见的手势事件,这些子类主要有: 1.首先创建几个view,来用于手势的检测 let view1 = UIView() let view2 ...
- MYSQL IFNULL函数的使用
IFNULL函数是MYSQL数据库中最重要的函数之一,下面就对该函数的使用方面进行分析,希望对您能够有所帮助. 下文对MYSQL IFNULL函数的使用进行了详细的叙述,供您参考学习,如果您在MYSQ ...
- Windows 下安装 Python3
可以使用两种方式安装 Python3,一种是直接去官网下载安装包,然后进行安装即可:另一种是通过安装 Anaconda 来安装 Python3, Anaconda 提供了 Python 的科学计算环境 ...
- Objective-c为什么要有属性
属性:为什么要有属性 . 首先是因为实例变量的安全性和继承能力,如果我们允许被继承,子类要动这些实例变量,我们需要能够参与进来,如果子类设置了某个值,我们需要检查范围,保证不会破坏父类,保证不会破坏父 ...
- 网络虚拟化技术(一): Linux网络虚拟化
创建虚拟网络环境 使用命令 $ ip netns add net0 可以创建一个完全隔离的新网络环境,这个环境包括一个独立的网卡空间,路由表,ARP表,ip地址表,iptables,ebtables, ...