【JVM】异常和return

版权声明:本文为原创文章,转载时请注明出处;文章如有错漏,烦请不吝指正,谢谢! https://blog.csdn.net/reliveIT/article/details/51162682

        参照下文字节码对应来看,环境JDK 8.

package exception;

/**
 * 1. 当只有try块中有return且能正常返回的时候,return的value被存放到局部变量表中,然后执行完finally之后才返回; 
 * 2. 当try和finally中都有return的时候,try块中的return会被优化掉,只会返回finally中; 
 * 3. 当try和catch中都有return的时候,异常返回catch,正常返回try; 
 * 4. 当try、catch和finally中都有return的时候
 * 		正常: try中的return被优化,直接返回finally中的return;
 * 		异常: try中的return不会被执行,catch中的代码被执行,返回finally中的value;
 */
public class FinallyTest {
	public static void main(String[] args) {
		System.out.println(getValueTry());
		System.out.println(getValueCatch());
		System.out.println(getValueFinally());
		System.out.println(getValueTryCatchFinally());
		/**
		 * 打印结果:
		 * 1
		 * 1
		 * 2
		 * 2
		 */
	}

	// 只有try中return
	public static int getValueTry() {
		int i = 1;
		try {
			/**
			 * 当执行完return i的时候,i的值被保存到局部变量表其他slot
			 * 等执行完finally之后,才会从该slot从返回
			 */
			return i; 
		} finally {
			/**
			 * 此时增加的是局部变量表中原来的i的值
			 * 待返回的值被保存到局部变量表中其他的位置,因此这里不影响返回值
			 */
			i++;
		}
	}

	// try和catch中return
	public static int getValueCatch() {
		int i = 1;
		try {
			/*if(i == 1)
				throw new Exception("xx");*/
			return i;
		} catch (Exception e) {
			return ++i;
		}
	}

	// try和finally中return
	@SuppressWarnings("finally")
	public static int getValueFinally() {
		int i = 1;
		try {
			/**
			 * try中的return在编译的时候就被优化掉了
			 */
			return i;
		} finally {
			i++;
			return i;
		}
	}

	// try、catch和finally中都有return
	@SuppressWarnings("finally")
	public static int getValueTryCatchFinally() {
		int i = 1;
		try {
			/**
			 * 1. 如果不相等(if_icmpne),则goto finally
			 * 意味着如果i != 100,那么try中的return被优化掉,直接跳到finally中执行
			 * 2. 如果相等,则到try块中执行,执行完后goto finally中执行
			 * 意味着如果1 == 100,那么走异常,try块中的return不会被执行,只执行catch和finally中的代码
			 * catch中的return被又化成iinc指令,而不是return指令
			 */
			if (i == 100)
				throw new Exception("xx");
			return i;
		} catch (Exception e) {
			return ++i;
		} finally {
			return ++i;
		}
	}
}
对应的字节码:

public class exception.FinallyTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Class              #2             // exception/FinallyTest
   #2 = Utf8               exception/FinallyTest
   #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               Lexception/FinallyTest;
  #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.#23         // exception/FinallyTest.getValueTry:()I
  #23 = NameAndType        #24:#25        // getValueTry:()I
  #24 = Utf8               getValueTry
  #25 = Utf8               ()I
  #26 = Methodref          #27.#29        // java/io/PrintStream.println:(I)V
  #27 = Class              #28            // java/io/PrintStream
  #28 = Utf8               java/io/PrintStream
  #29 = NameAndType        #30:#31        // println:(I)V
  #30 = Utf8               println
  #31 = Utf8               (I)V
  #32 = Methodref          #1.#33         // exception/FinallyTest.getValueCatch:()I
  #33 = NameAndType        #34:#25        // getValueCatch:()I
  #34 = Utf8               getValueCatch
  #35 = Methodref          #1.#36         // exception/FinallyTest.getValueFinally:()I
  #36 = NameAndType        #37:#25        // getValueFinally:()I
  #37 = Utf8               getValueFinally
  #38 = Methodref          #1.#39         // exception/FinallyTest.getValueTryCatchFinally:()I
  #39 = NameAndType        #40:#25        // getValueTryCatchFinally:()I
  #40 = Utf8               getValueTryCatchFinally
  #41 = Utf8               args
  #42 = Utf8               [Ljava/lang/String;
  #43 = Utf8               i
  #44 = Utf8               I
  #45 = Utf8               StackMapTable
  #46 = Class              #47            // java/lang/Throwable
  #47 = Utf8               java/lang/Throwable
  #48 = Class              #49            // java/lang/Exception
  #49 = Utf8               java/lang/Exception
  #50 = Utf8               e
  #51 = Utf8               Ljava/lang/Exception;
  #52 = String             #53            // xx
  #53 = Utf8               xx
  #54 = Methodref          #48.#55        // java/lang/Exception."<init>":(Ljava/lang/String;)V
  #55 = NameAndType        #5:#56         // "<init>":(Ljava/lang/String;)V
  #56 = Utf8               (Ljava/lang/String;)V
  #57 = Utf8               SourceFile
  #58 = Utf8               FinallyTest.java
{
  public exception.FinallyTest();
    descriptor: ()V
    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 11: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lexception/FinallyTest;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: invokestatic  #22                 // Method getValueTry:()I
         6: invokevirtual #26                 // Method java/io/PrintStream.println:(I)V
         9: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
        12: invokestatic  #32                 // Method getValueCatch:()I
        15: invokevirtual #26                 // Method java/io/PrintStream.println:(I)V
        18: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
        21: invokestatic  #35                 // Method getValueFinally:()I
        24: invokevirtual #26                 // Method java/io/PrintStream.println:(I)V
        27: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
        30: invokestatic  #38                 // Method getValueTryCatchFinally:()I
        33: invokevirtual #26                 // Method java/io/PrintStream.println:(I)V
        36: return
      LineNumberTable:
        line 13: 0
        line 14: 9
        line 15: 18
        line 16: 27
        line 24: 36
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      37     0  args   [Ljava/lang/String;

  public static int getValueTry();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=3, args_size=0
         0: iconst_1
         1: istore_0
         2: iload_0
         3: istore_2
         4: iinc          0, 1
         7: iload_2
         8: ireturn
         9: astore_1
        10: iinc          0, 1
        13: aload_1
        14: athrow
      Exception table:
         from    to  target type
             2     4     9   any
      LineNumberTable:
        line 28: 0
        line 34: 2
        line 40: 4
        line 34: 7
        line 35: 9
        line 40: 10
        line 41: 13
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            2      13     0     i   I
      StackMapTable: number_of_entries = 1
        frame_type = 255 /* full_frame */
          offset_delta = 9
          locals = [ int ]
          stack = [ class java/lang/Throwable ]

  public static int getValueCatch();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=2, args_size=0
         0: iconst_1
         1: istore_0
         2: iload_0
         3: ireturn
         4: astore_1
         5: iinc          0, 1
         8: iload_0
         9: ireturn
      Exception table:
         from    to  target type
             2     3     4   Class java/lang/Exception
      LineNumberTable:
        line 46: 0
        line 50: 2
        line 51: 4
        line 52: 5
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            2       8     0     i   I
            5       5     1     e   Ljava/lang/Exception;
      StackMapTable: number_of_entries = 1
        frame_type = 255 /* full_frame */
          offset_delta = 4
          locals = [ int ]
          stack = [ class java/lang/Exception ]

  public static int getValueFinally();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=0
         0: iconst_1
         1: istore_0
         2: goto          6
         5: pop
         6: iinc          0, 1
         9: iload_0
        10: ireturn
      Exception table:
         from    to  target type
             2     5     5   any
      LineNumberTable:
        line 59: 0
        line 64: 2
        line 65: 5
        line 66: 6
        line 67: 9
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            2       9     0     i   I
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 5
          locals = [ int ]
          stack = [ class java/lang/Throwable ]
        frame_type = 0 /* same */

  public static int getValueTryCatchFinally();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=0
         0: iconst_1
         1: istore_0
         2: iload_0
         3: bipush        100
         5: if_icmpne     26
         8: new           #48                 // class java/lang/Exception
        11: dup
        12: ldc           #52                 // String xx
        14: invokespecial #54                 // Method java/lang/Exception."<init>":(Ljava/lang/String;)V
        17: athrow
        18: astore_1
        19: iinc          0, 1
        22: goto          26
        25: pop
        26: iinc          0, 1
        29: iload_0
        30: ireturn
      Exception table:
         from    to  target type
             2    18    18   Class java/lang/Exception
             2    25    25   any
      LineNumberTable:
        line 74: 0
        line 76: 2
        line 77: 8
        line 79: 18
        line 80: 19
        line 81: 25
        line 82: 26
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            2      29     0     i   I
           19       6     1     e   Ljava/lang/Exception;
      StackMapTable: number_of_entries = 3
        frame_type = 255 /* full_frame */
          offset_delta = 18
          locals = [ int ]
          stack = [ class java/lang/Exception ]
        frame_type = 70 /* same_locals_1_stack_item */
          stack = [ class java/lang/Throwable ]
        frame_type = 0 /* same */
}
SourceFile: "FinallyTest.java"


附注:

        如有错漏,烦请不吝指正,谢谢!

猜你喜欢

转载自blog.csdn.net/reliveIT/article/details/51162682