finally源码
public class Test { public static void main(String[] args) { System.out.println(new Test().test()); } int test() { try { return func1(); } finally { return func2(); } } int func1() { System.out.println("func1"); return 1; } int func2() { System.out.println("func2"); return 2; } }
编译后字节码
Last modified 2015-10-17; size 901 bytes MD5 checksum f2beb1a91e4cb99abea1e1f61b1f3176 Compiled from "Test.java" public class com.lw.loader.Test SourceFile: "Test.java" minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Class #2 // com/lw/loader/Test #2 = Utf8 com/lw/loader/Test #3 = Class #4 // java/lang/Object #4 = Utf8 java/lang/Object #5 = Utf8 <init> #6 = Utf8 ()V #7 = Utf8 Code #8 = Methodref #3.#9 // java/lang/Object."<init>":()V #9 = NameAndType #5:#6 // "<init>":()V #10 = Utf8 LineNumberTable #11 = Utf8 LocalVariableTable #12 = Utf8 this #13 = Utf8 Lcom/lw/loader/Test; #14 = Utf8 main #15 = Utf8 ([Ljava/lang/String;)V #16 = Fieldref #17.#19 // java/lang/System.out:Ljava/io/PrintStream; #17 = Class #18 // java/lang/System #18 = Utf8 java/lang/System #19 = NameAndType #20:#21 // out:Ljava/io/PrintStream; #20 = Utf8 out #21 = Utf8 Ljava/io/PrintStream; #22 = Methodref #1.#9 // com/lw/loader/Test."<init>":()V #23 = Methodref #1.#24 // com/lw/loader/Test.test:()I #24 = NameAndType #25:#26 // test:()I #25 = Utf8 test #26 = Utf8 ()I #27 = Methodref #28.#30 // java/io/PrintStream.println:(I)V #28 = Class #29 // java/io/PrintStream #29 = Utf8 java/io/PrintStream #30 = NameAndType #31:#32 // println:(I)V #31 = Utf8 println #32 = Utf8 (I)V #33 = Utf8 args #34 = Utf8 [Ljava/lang/String; #35 = Methodref #1.#36 // com/lw/loader/Test.func1:()I #36 = NameAndType #37:#26 // func1:()I #37 = Utf8 func1 #38 = Methodref #1.#39 // com/lw/loader/Test.func2:()I #39 = NameAndType #40:#26 // func2:()I #40 = Utf8 func2 #41 = Utf8 StackMapTable #42 = Class #43 // java/lang/Throwable #43 = Utf8 java/lang/Throwable #44 = String #37 // func1 #45 = Methodref #28.#46 // java/io/PrintStream.println:(Ljava/lang/String;)V #46 = NameAndType #31:#47 // println:(Ljava/lang/String;)V #47 = Utf8 (Ljava/lang/String;)V #48 = String #40 // func2 #49 = Utf8 SourceFile #50 = Utf8 Test.java { public com.lw.loader.Test(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #8 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/lw/loader/Test; public static void main(java.lang.String[]); flags: ACC_PUBLIC, ACC_STATIC Code: stack=3, locals=1, args_size=1 0: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream; 3: new #1 // class com/lw/loader/Test 6: dup 7: invokespecial #22 // Method "<init>":()V 10: invokevirtual #23 // Method test:()I 13: invokevirtual #27 // Method java/io/PrintStream.println:(I)V 16: return LineNumberTable: line 5: 0 line 7: 16 LocalVariableTable: Start Length Slot Name Signature 0 17 0 args [Ljava/lang/String; int test(); flags: Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokevirtual #35 // Method func1:()I 4: pop 5: goto 9 8: pop 9: aload_0 10: invokevirtual #38 // Method func2:()I 13: ireturn Exception table: from to target type 0 8 8 any LineNumberTable: line 11: 0 line 12: 8 line 13: 9 LocalVariableTable: Start Length Slot Name Signature 0 14 0 this Lcom/lw/loader/Test; StackMapTable: number_of_entries = 2 frame_type = 72 /* same_locals_1_stack_item */ stack = [ class java/lang/Throwable ] frame_type = 0 /* same */ int func1(); flags: Code: stack=2, locals=1, args_size=1 0: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #44 // String func1 5: invokevirtual #45 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: iconst_1 9: ireturn LineNumberTable: line 18: 0 line 19: 8 LocalVariableTable: Start Length Slot Name Signature 0 10 0 this Lcom/lw/loader/Test; int func2(); flags: Code: stack=2, locals=1, args_size=1 0: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #48 // String func2 5: invokevirtual #45 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: iconst_2 9: ireturn LineNumberTable: line 23: 0 line 24: 8 LocalVariableTable: Start Length Slot Name Signature 0 10 0 this Lcom/lw/loader/Test; }
public class TestRef { public static void main(String[] args) { System.out.println(new TestRef().test()); } TestP test() { try { return func1(); } catch (Exception e) { return new TestP(); } finally { // return func2(); } } TestP func1() { System.out.println("func1"); return new TestA(); } TestP func2() { System.out.println("func2"); return new TestB(); } }
com.lw.loader.TestP test(); flags: Code: stack=2, locals=4, args_size=1 0: aload_0 1: invokevirtual #35 // Method func1:()Lcom/lw/loader/TestP; 4: astore_3 5: aload_0 6: invokevirtual #38 // Method func2:()Lcom/lw/loader/TestP; 9: pop 10: aload_3 11: areturn 12: astore_1 13: new #41 // class com/lw/loader/TestP 16: dup 17: invokespecial #43 // Method com/lw/loader/TestP."<init>":()V 20: astore_3 21: aload_0 22: invokevirtual #38 // Method func2:()Lcom/lw/loader/TestP; 25: pop 26: aload_3 27: areturn 28: astore_2 29: aload_0 30: invokevirtual #38 // Method func2:()Lcom/lw/loader/TestP; 33: pop 34: aload_2 35: athrow Exception table: from to target type 0 5 12 Class java/lang/Exception 0 5 28 any 12 21 28 any LineNumberTable:
简单看过代码就能知道执行流程,但是从字节码中能让我们对执行流程有更深刻的理解。
《深入理解java虚拟机》有相似代码对正常、异常、finally代码流程进行讲解,唯一困惑的是正常流程中的return字节码中没有编译。
待研究!!!!!!!!!!