从finally看class编译字节码

时间:2022-12-13 17:05:06

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字节码中没有编译。

待研究!!!!!!!!!!