今天来看一看字节码中的异常处理表。
public class ReadFileHelper {
public void readFile(){
try {
InputStream inputStream = new FileInputStream("test.txt");
ServerSocket serverSocket = new ServerSocket(4200);
serverSocket.accept();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
System.out.println("call finally method...");
}
}
}
-
StackMap Table 在 JDK 1.7 以后进行静态数据校验,
code 助记符 - new : 创建一个新的对象
- dup :
public void readFile()
stack=3, locals=4, args_size=1
- stack=3:最大深度
- args_size=1 : 这里在
readFile()
有一个参数为 this。 - locals=4 : 局部变量为
- this
- inputStream
- serverSocket
- ex
虽然有 3 catch 来捕获对象,但是只是走一个 catch 所以异常对象只会一个作为局部变量。
每一个 exception_table(异常处理表)表项由 start_pc, end_pc, handler_pc , catch_type 组成。
- start_pc 和 end_pc 表示在 code 数组中的从 start_pc 到 end_pc 处(包括 start_pc, 不包含 end_pc) 的指令抛出的异常会由这个表项来处理
- handler_pc 表示处理异常的代码的开始处。catch_type 表示会被处理的异常类型,指向常量池里的一个异常类。当 catch_type 为 0 时,表示处理所有异常。
发生异常会使用goto
语句进行跳转到异常处理的位置。
- new :创建对象
- dup : 复制操作栈的顶层然后入栈
- ldc :将常量池获取信息
- inovkespecial : 调用父类构造方法
- astore_1 : new FileInputStream 创建对象复制给 inputStream 局部变量进行存储
下面同上 - pop 从栈进行弹出
- getstatic 调用 System.out.Print 静态方法
- 异常表最后一个 any 表示处理以上列出异常以外,都有此异常处理来处理。
- 0 -26 出现了 FileNotFoundException 异常就会转到 37 进行处理,
astore_1
赋值给局部变量。 - 0 - 26 如果出现对应IOException 就会跳转 37 进行处理,
astore_1
赋值给局部变量。
字节码中 Java 对异常的处理
- 统一采用异常表的方法来对异常进行处理
- 当异常处理存在 finally 语句块,现在 JVM 将 finally 的语句块字节码拼接到每一个 catch 块后。
网友评论