《深入理解Java虚拟机》学习笔记(6)——try-catch-finally

资料总结自:《深入理解Java虚拟机》 周志明 著


 

下面代码演示了字节码层面中try-catch-finally是如何实现的。

编译后的ByteCode字节码及异常表

编译器为这段Java源码生成了3条异常表记录,对应3条可能出现的代码执行路径。从Java代码的语义上讲,这3条执行路径分别为:

  • 如果try语句块中出现属于Exception或其子类的异常,则转到catch语句块处理,然后转到finally语句块处理。
  • 如果try语句块中出现不属于Exception或其子类的异常,则转到finally语句块处理,然后抛出异常。
  • 如果catch语句块中出现任何异常,则转到finally语句块处理。

对于这段代码返回值:

  • 如果没有出现异常,返回值是1
  • 如果出现了属于Exception或其子类的异常,返回值是2
  • 如果出现了属于Exception或其子类以外的异常,方法非正常退出,没有返回值。

字节码中第0~4行所做的操作就是讲整数1赋值给变量 x ,并且将此时 x 的值复制一份副本到最后一个本地变量表的Slot中(这个Slot里面的值在ireturn指令执行前将会被重新读到操作栈顶,作为方法返回值使用,为了讲解方便,这里给Slot起了个名字: returnValue )。

如果这时没有出现异常,则会继续走到5~9行,将变量 x 赋值为3,然后将之前保存在 returnValue 中的整数1读入到操作栈顶,最后ireturn指令会以int形式返回操作栈顶中的值,方法结束。

如果出现了属于Exception或其子类的异常,PC寄存器指针转到第10行,第10~20行所做的事情是将2赋值给变量 x ,然后将变量 x 此时的值赋值给 returnValue ,最后再将变量 x 的值改为3。方法返回前同样将 returnValue 中保留的整数2读到了操作栈顶。

如果出现了属于Exception或其子类以外的异常,则PC寄存器指针转到第21行,第21行开始的代码,作用是变量 x 的值赋为3,并将栈顶的异常抛出,方法结束。

Categories: Java