在编译级别1.4时jvm编译try/catch/finally块的方式
? ? ? ? 先上一段很简单,且不考虑健壮性的源码:
import java.io.FileInputStream;import java.io.IOException;public class TryCatchFinallyTest {/** * @param args * @throws IOException */public static void main(String[] args) throws IOException {FileInputStream fips = null;try {fips = new FileInputStream("hello.txt");fips.read();} catch (IOException e) {e.printStackTrace();} finally {fips.close();}}}? ? ? ? ?然后上一段这段代码在eclipse编译级别为1.4、没有inline finally块时编译出的字节码:
// Compiled from TryCatchFinallyTest.java (version 1.2 : 46.0, super bit)public class TryCatchFinallyTest { // Method descriptor #6 ()V // Stack: 1, Locals: 1 public TryCatchFinallyTest(); 0 aload_0 [this] 1 invokespecial java.lang.Object() [8] 4 return Line numbers: [pc: 0, line: 6] Local variable table: [pc: 0, pc: 5] local: this index: 0 type: TryCatchFinallyTest // Method descriptor #15 ([Ljava/lang/String;)V // Stack: 3, Locals: 5 public static void main(java.lang.String[] args) throws java.io.IOException; 0 aconst_null 1 astore_1 [fips] 2 new java.io.FileInputStream [19] 5 dup 6 ldc <String "hello.txt"> [21] 8 invokespecial java.io.FileInputStream(java.lang.String) [23] 11 astore_1 [fips] 12 aload_1 [fips] 13 invokevirtual java.io.FileInputStream.read() : int [26] 16 pop 17 goto 43 20 astore_2 [e] 21 aload_2 [e] 22 invokevirtual java.io.IOException.printStackTrace() : void [30] 25 goto 43 28 astore 4 30 jsr 36 33 aload 4 35 athrow 36 astore_3 37 aload_1 [fips] 38 invokevirtual java.io.FileInputStream.close() : void [33] 41 ret 3 43 jsr 36 46 return Exception Table: [pc: 2, pc: 17] -> 20 when : java.io.IOException [pc: 2, pc: 25] -> 28 when : any [pc: 43, pc: 46] -> 28 when : any Line numbers: ...... Local variable table: [pc: 0, pc: 47] local: args index: 0 type: java.lang.String[] [pc: 2, pc: 47] local: fips index: 1 type: java.io.FileInputStream [pc: 21, pc: 25] local: e index: 2 type: java.io.IOException}? ? ? ? ?2-17是try块代码;
? ? ? ? ? ?20-25是catch块代码;
? ? ? ? ? ?28-35是编译期生产的catch块之外的异常即any类型异常要执行的代码;
? ? ? ? ? ?36-41是finally块代码;
? ? ? ? ? ?43-46是编译期生成的字节码;
? ? ? ? ? ?其中偏移量17和25处都是goto 43,然后jsr到finally,即try和catch块都是到43;any类型中有一条指令jsr到finally块。
? ? ? ? 归纳总结下,try/catch/finally结构中:
? ? ? ? 1、try/catch块翻译成指令后最后一条字节码指令都是goto到一个编译出来的块A(43-46),A第一条指令(43)即jsr到finally块第一条指令,finally完就ret到A第二条指令即return(46)
? ? ? ? 2、any块,即catch之外的异常类型,也即any,是jvm自己构造了一个指令块B(28-35),先store下这种异常实例到局部变量表(28),然后jsr到finally块中(30),finally完就ret到B的第三条指令(33)执行,load出之前存储到局部变量表的异常实例,然后athrow(35)。
?
? ? ? ? JSR指令后边一般是:
? ? ? ? 1、load返回值然后return的指令(try/catch块,有返回值)
? ? ? ? 2、直接return(try/catch块,无返回值)
? ? ? ? 3、load出异常然后athrow(catch any)
?