JVM 字节码(三)异常在字节码中的处理(catch 和 throws)

在 ClassFile 中到底是如何处理异常的呢?

一、代码块异常 catch

catch 中的异常代码块在异常是如何处理的呢?还记得在 Code 属性中有如下的结构吗?这代码的是一个异常表信息。

Code_attribute {
...
u2 exception_table_length;
{ u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type;
} exception_table[exception_table_length];
...
}

案例分析:

public void test() {
try {
FileInputStream in = new FileInputStream("text.txt");
ServerSocket serverSocket = new ServerSocket(9999);
serverSocket.accept();
} catch (FileNotFoundException e) {
} catch (IOException e) {
} catch (Exception e) {
} finally {
System.out.println("finally!");
}
}

这段代码编译后用 jclasslib 查看,字节码和异常表分别如下:

 0 new #2 <java/io/FileInputStream>
3 dup
4 ldc #3 <text.txt>
6 invokespecial #4 <java/io/FileInputStream.<init>>
9 astore_1
10 new #5 <java/net/ServerSocket>
13 dup
14 sipush 9999
17 invokespecial #6 <java/net/ServerSocket.<init>>
20 astore_2
21 aload_2
22 invokevirtual #7 <java/net/ServerSocket.accept>
25 pop
26 getstatic #8 <java/lang/System.out>
29 ldc #9 <finally!>
31 invokevirtual #10 <java/io/PrintStream.println>
34 goto 84 (+50)
37 astore_1
38 getstatic #8 <java/lang/System.out>
41 ldc #9 <finally!>
43 invokevirtual #10 <java/io/PrintStream.println>
46 goto 84 (+38)
49 astore_1
50 getstatic #8 <java/lang/System.out>
53 ldc #9 <finally!>
55 invokevirtual #10 <java/io/PrintStream.println>
58 goto 84 (+26)
61 astore_1
62 getstatic #8 <java/lang/System.out>
65 ldc #9 <finally!>
67 invokevirtual #10 <java/io/PrintStream.println>
70 goto 84 (+14)
73 astore_3
74 getstatic #8 <java/lang/System.out>
77 ldc #9 <finally!>
79 invokevirtual #10 <java/io/PrintStream.println>
82 aload_3
83 athrow
84 return

异常表如下:

解读一下异常表, start_pc ~ end_pc 出现的 catch_type 异常由 handler_pc 行的代码进行处理。

  • 第一行表示 0~26 行出现的 FileNotFoundException 异常直接跳转到 37(astore_1) 行
  • 第二行表示 0~26 行出现的 IOException 异常直接跳转到 49(astore_1) 行
  • 第三行表示 0~26 行出现的 Exception 异常直接跳转到 61(astore_1) 行
  • any 表示其余的所有异常,字节码层面定义,和 Java 中定义的 Exception 还不太一样

总结:Java 字节码对于异常的处理方式

  1. 统一采用异常表的方式对异常进行处理。
  2. 在 JDK 1.4.2 之前的版本中,采用特定的指令方式。
  3. 当异常处理存在 finally 语句块时,JVM 采取的处理方式是将 finally 语句块的字节码拼接到每一个 catch 块后面

二、方法级异常 throws

public void test() throws FileNotFoundException, RuntimeException {
}

在上述方法上加上 FileNotFoundException, RuntimeException 两个异常重新编译后的字节码,方法多了一个 Exceptions 属性,这个属性和 Code 属性平级。

参考:

  1. 周志明,深入理解Java虚拟机 - 第 6 章:类文件结构
  2. Java 反编译工具 - jclasslib(比 javap -v 信息更详细,可以在 IDEA 插件中直接下载)

每天用心记录一点点。内容也许不重要,但习惯很重要!

JVM 字节码(三)异常在字节码中的处理(catch 和 throws)的更多相关文章

  1. 卷向字节码-Java异常到底是怎么被处理的?

    你好呀,我是why,你也可以叫我歪歪. 比如下面这位读者: 他是看了我<神了!异常信息突然就没了?>这篇文章后产生的疑问. 既然是看了我的文章带来的进一步思考,恰巧呢,我又刚好知道. 虽然 ...

  2. JVM 字节码(一)字节码规范

    JVM 字节码(一)字节码规范 JVM 学习资源 Java ClassFile 字节码规范(Oracle) Java 虚拟机规范(Java SE 7 中文版) (周志明等译) Java 反编译工具 - ...

  3. 三联运算&&字节码转换

    三联运算 if 1 == 1: name = 'alex'else: name = 'sb' name = 'alex' if 1 == 1 else 'sb lambda f2 = lambda a ...

  4. OpenJDK源码研究笔记(七)–Java字节码文件(.class)的结构

    最近在看OpenJDK源码的过程中,顺便看了Java编译器(javac)的源码. 为了理解javac的源码,需要先搞懂Java字节码文件(.class)的结构. 于是,我就认真看了下OpenJDK中J ...

  5. UTF-8格式txt文件读取字节前三位问题

    今天试着读取一份UTF-8格式的txt文件,内容如下 12345 但是每次读取之后转为String类型,输出字符串长度总是为6,并且第一位打印在控制台后不占任何空间. 经过debug查看字节码后发现, ...

  6. C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)

    前言:之前的两篇封装了一些基础的表单组件,这篇继续来封装几个基于bootstrap的其他组件.和上篇不同的是,这篇的有几个组件需要某些js文件的支持. 本文原创地址:http://www.cnblog ...

  7. Java 序列化和反序列化(三)Serializable 源码分析 - 2

    目录 Java 序列化和反序列化(三)Serializable 源码分析 - 2 1. ObjectStreamField 1.1 数据结构 1.2 构造函数 2. ObjectStreamClass ...

  8. AQS源码三视-JUC系列

    AQS源码三视-JUC系列 前两篇文章介绍了AQS的核心同步机制,使用CHL同步队列实现线程等待和唤醒,一个int值记录资源量.为上层各式各样的同步器实现画好了模版,像已经介绍到的ReentrantL ...

  9. Spring AOP实现方式三【附源码】

    注解AOP实现 源码结构: 1.首先我们新建一个接口,love 谈恋爱接口. package com.spring.aop; /** * 谈恋爱接口 * * @author Administrator ...

随机推荐

  1. Qt配置cmake;运行带参数的程序

    配置cmake编译器,步骤如下: 步骤1:  Qt下新建一个project. 步骤2:  在该project目录下创建一个CMakeLists.txt文件,并按规范编写该文件. Tip: projec ...

  2. springMVC框架返回JSON到前端日期格式化

    在Controller类中,需要返回JSON的方法上加上注释@ResponseBody,这是必须的. 然后spring-servlet.xml配置如下: <?xml version=" ...

  3. vue+窗格切换+田字+dicom显示_01

    环境:vue+webpack+cornerstone ide:vs code 需求:窗格设置+拼图设置 1.点击左边第一个窗格或者默认显示. 2.点击第二个也同理显示,以此类推 3.选择左边的窗格之后 ...

  4. 用户名、密码等15个常用的js正则表达式

    本文收集整理了15个常用的javaScript正则表达式,其中包括用户名.密码强度.整数.数字.电子邮件地址(Email).手机号码.身份证号.URL地址. IPv4地址. 十六进制颜色. 日期. Q ...

  5. thinkphp5 Exception类重定义

    重点定义自己的错误信息和错误码: 在TP5的配置文件中有下面一段 // 异常处理handle类 留空使用 \think\exception\Handle 'exception_handle' => ...

  6. tensorflow实战系列(四)基于TensorFlow构建AlexNet代码解析

    整体流程介绍: 我们从main函数走,在train函数中,首先new了一个network;然后初始化后开始训练,训练时设定设备和迭代的次数,训练完后关闭流程图. 下面看network这个类,这个类有许 ...

  7. Maven项目中遇到的问题及其解决方案

    Maven中pom报红 1.jdk版本是否符合要求? 2.maven的本地confg中的setting.xml中是否和要求的jdk版本一致? 3.maven本地仓库路径是否正确,即为自己的确定的仓库位 ...

  8. PAT甲级

    https://www.cnblogs.com/jlyg/p/7525244.html 哇咔咔,瞧人家都刷完甲级130道题了,哼,有什么了不起的,考前刷完,再刷的比你多,哼,照样吊打. 沙耶加油! 一 ...

  9. Python面向对象编程(上)

    Python不仅支持面向过程编程,同时也支持面向对象编程.面向工程就是分析解决问题所需的步骤,然后用函数把这些步骤逐一实现,使用的时候再一个个调用函数就可以.面向对象则是把解决的问题按照一定规则划分为 ...

  10. Controller层aop

    利用@Around通知修改Controller的返回值 自定义一个注解@OperationBtn 在切入点Controller上加上自定义注解 接下来就是重点了,AspectJ写切面类,对该Contr ...