字节码指令之异常处理指令
目录
一、抛出异常指令
二、异常处理与异常表
一、抛出异常指令
- (1)athrow指令
在Java程序中显示抛出异常的操作 (throw语句)都是由athrow指令来实现。
除了使用throw语句显示抛出异常情况之外,JVM规范还规定了许多运行时异常会在其他Java虚拟机指令检测到异常状况时自动抛出。例如,在之前介绍的整数运算时,当除数为零时,虚拟机会在 idiv或 ldiv指令中抛出 ArithmeticException异常。
- (2)注意
正常情况下,操作数栈的压入弹出都是一条条指令完成的。唯一的例外情况是在抛异常时,Java虚拟机会清除操作数栈上的所有内容,而后将异常实例压入调用者操作数栈上。
异常及异常的处理:
- 过程一:异常对象的生成过程 --> throw(手动 / 自动) --> 指令:athrow;
- 过程二:异常的处理:抓抛模型 --> try-catch-finally --> 使用异常表;
public void test01(int i) {if (i == 0) {throw new RuntimeException("参数不能为0");}
}
查看其字节码信息:
0 iload_1 //将局部变量表中索引为1的值加载到操作数栈中,即i的值1 ifne 14 (+13) //条件判断 判断i的值是否不等于0,满足条件的话直接跳转到14,直接return,如果不满足,继续执行下面的指令4 new #2 <java/lang/RuntimeException> //如果i的值等于0,这里new一个RuntimeException实例7 dup8 ldc #3 <参数不能为0> //将字符串常量加载到操作数栈中
10 invokespecial #4 <java/lang/RuntimeException.<init>> //执行RuntimeException的<init>方法进行初始化
13 athrow //将刚刚创建的RuntimeException实例的异常对象抛出
14 return //方法返回
在方法声明处指定了抛出的异常:
public void test02(int i) throws RuntimeException {if (i == 1) {throw new RuntimeException("参数值为1");}
}
可见,方法声明处指定抛出的异常后,字节码文件中多了一个属性Exceptions。
二、异常处理与异常表
1. 处理异常
在Java虚拟机中,处理异常(catch语句)不是由字节码指令来实现的(早期使用jsr、ret指令),而是采用异常表来完成的。
2. 异常表
如果一个方法定义了一个try-catch或者try-finally的异常处理,就会创建一个异常表。它包含了每个异常处理或者finally块的信息,异常表保存了每个异常处理信息。比如: - 起始位置 - 结束位置 - 程序计数器记录的代码处理的偏移地址 - 被捕获的异常类在常量池中的索引。
当一个异常被抛出时,JVM会在当前的方法里寻找一个匹配的处理,如果没有找到,这个方法会强制结束并弹出当前栈帧,并且异常会重新抛给上层调用的方法(在调用方法栈帧)。如果在所有栈帧弹出前仍然没有找到合适的异常处理,这个线程将终止。如果这个异常在最后一个非守护线程里抛出,将会导致JVM自己终止,比如这个线程是个main线程。
不管什么时候抛出异常,如果异常处理最终匹配了所有异常类型,代码就会继续执行。在这种情况下,如果方法结束后没有抛出异常,仍然执行finally块,在return前,它直接跳到finally块来完成目标。
public void test03() {try {File file = new File("");FileInputStream inputStream = new FileInputStream(file);} catch (FileNotFoundException e1) {e1.printStackTrace();} catch (RuntimeException e2) {e2.printStackTrace();}
}
异常表说明:
- 如果在0-19行之间发生了FileNotFoundException的话,就使用22行进行异常处理;
- 如果在0-19行之间发生了RuntimeException的话,就使用30行进行异常处理;
查看其字节码信息如下:
0 new #6 <java/io/File> //创建一个File实例3 dup //复制4 ldc #7 //将字符串常量池表中#7对应的字符串加载到操作数栈中6 invokespecial #8 <java/io/File.<init>> //执行File的init方法进行初始化9 astore_1 //将file对象存入局部变量表中索引为1的位置
10 new #9 <java/io/FileInputStream> //创建一个FileInputStream实例
13 dup //复制
14 aload_1 //将局部变量表中索引为1的变量,即File对象加载到操作数栈中
15 invokespecial #10 <java/io/FileInputStream.<init>> //执行FileInputStream的init方法进行初始化
18 astore_2 //将FileInputStream对象存入局部变量表中索引为2的位置
19 goto 35 (+16) //跳转到35行return指令,表示结束了
#############处理FileNotFoundException异常############
22 astore_1
23 aload_1
24 invokevirtual #12 <java/io/FileNotFoundException.printStackTrace>
27 goto 35 (+8)
#############处理RuntimeException异常#################
30 astore_1
31 aload_1
32 invokevirtual #13 <java/lang/RuntimeException.printStackTrace>
35 return //方法返回
try-finally代码执行过程举例:
public static String test04() {String str = "hello";try {return str;} finally {str = "world";}
}
如果3-5行之间发生任何异常,则使用第10行进行异常处理。
查看其字节码信息如下:
0 ldc #15 <hello> //hello进入操作数栈中2 astore_0 //将hello保存到局部变量表中索引为0的位置3 aload_0 //将hello又重新加载到操作数栈中4 astore_1 //将hello又保存一份到局部变量表中索引为1的位置5 ldc #16 <world> //将world加载到操作数栈中7 astore_0 //此时局部变量表中索引为0的hello被world替换了8 aload_1 //因为第4行多保存了一份hello,此时将hello加载到操作数栈中9 areturn //然后将hello进行返回#############异常处理##############
10 astore_2 //将发生的异常对象保存到局部变量表中索引为2的位置
11 ldc #16 <world> //将world加载到操作数栈中
13 astore_0
14 aload_2
15 athrow //抛出异常对象
字节码指令之异常处理指令相关推荐
- [三] java虚拟机 JVM字节码 指令集 bytecode 操作码 指令分类用法 助记符
说明,本文的目的在于从宏观逻辑上介绍清楚绝大多数的字节码指令的含义以及分类 只要认真阅读本文必然能够对字节码指令集有所了解 如果需要了解清楚每一个指令的具体详尽用法,请参阅虚拟机规范 指令简介 计算机 ...
- java异常 字节码,Java字节码角度分析异常处理
目录 从字节码角度来分析:异常处理 1.1 异常-catch // 从字节码角度来分析:异常处理 public class T13_ByteAnalyseException { public stat ...
- Java指令全集_Java的JVM字节码指令集详解
本文详细介绍了如何使用javap查看java方法中的字节码.以及各种字节码的含义,并且配以完善的案例,一步步,从头到尾带领大家翻译javap的输出.在文末还附有JVM字节码指令集表. 本文不适合没有J ...
- 有哪些常见的字节码指令?
写在前面 本文隶属于专栏<100个问题搞定Java虚拟机>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和文献引用请见100个问题搞定Java ...
- Java虚拟机字节码指令
Java字节码指令 Java 字节码指令及javap 使用说明 ### java字节码指令列表 字节码 助记符 指令含义 0x00 nop 什么都不做 0x01 aconst_null 将null推送 ...
- Java 指令与字节码
Java 指令与字节码 查看class文件 编写简单java代码 编译代码 查看class文件 Java字节码总的结构表 常量池 常量池容量计数器 字面量和符号引用 全限定名 简单名称 描述符 常量类 ...
- Java字节码指令大全
Java二进制指令代码解析 Java源码在运行之前都要编译成为字节码格式(如.class文件),然后由ClassLoader将字节码载入运行.在字节码文件中,指令代码只是其中的一部分,里面还记录了字节 ...
- 深入理解虚拟机之虚拟机字节码执行引擎
1 概述 执行引擎是java虚拟机最核心的组成部件之一.虚拟机的执行引擎由自己实现,所以可以自行定制指令集与执行引擎的结构体系,并且能够执行那些不被硬件直接支持的指令集格式. 所有的Java虚拟机的执 ...
- Java字节码角度分析:Synchronized ——提升硬实力11
在前面的文章中,有详细地介绍java字节码相关的知识,有兴趣的可以提前了解一下. 1.Java字节码的一段旅行经历--提升硬实力1 2.Java字节码角度分析a++ --提升硬实力2 3.Java字节 ...
- JVM系列(十七):字节码指令集
1.概述 属于基本的执行指令 由操作码(1个字节)和操作数组成 1.1.执行模型 执行模型如下伪代码 1.2.字节码和数据类型 大多数指令都包含了操作所对应的数据类型信息,比如iload从局部变量表中 ...
最新文章
- python编写脚本方法_【Python】教你一步步编写banner获取脚本
- 猎豹浏览器怎么不能设置背景着颜色护眼?
- python 获取指定目录下的图片文件
- python字典遍历的几种方法(转)
- centos7下使用git
- pip install 到指定的目录下,查看pip包位置
- 迭代器,lower_bound说明
- 【蓝桥杯】历年真题题目及题解汇总
- python笔记-find()函数的用法
- 历代Windows版本
- OpenGL第三方库:glad初始了解与下载
- idefo功能模型图_如何画架构图?
- 项目进度管理:活动之间的四种依赖关系
- file Java 读取_Java读取文件方法汇总
- python百度地图api添加坐标点_python调用百度地图API实现经纬度换算、热力地图全流程指南...
- dux修改index.php,DUX主题修改首页轮播图为通栏模式
- 没有寻线仪怎么找网线_乱七八糟的网线怎么找?寻线仪来帮你
- android T分屏流程
- 美团店铺评价语言处理以及分类(tfidf,SVM,决策树,随机森林,Knn,ensemble)...
- 小程序的大于小于等于的写法
热门文章
- 易筋SpringBoot 2.1 | 第三十四篇:Spring Boot导出war包部署到外部Tomcat
- 易筋SpringBoot 2.2 | 第三十二篇:Redis Docker入门
- 易筋SpringBoot 2.1 | 第十一篇:SpringBoot使用actuator
- ORC File文件结构
- 在排序数组中查找数字
- jsp语法 --模板元素,表达式,脚本片段,声明,注释
- SpringBoot中的文件读取
- 论文引介 | Information Extraction with Reinforcement Learning
- 如何生成随机数(上)
- 偶们院就业相关政策及问题解答----吃面