您的位置:首页 > 其它

【JVM】异常和return

2016-04-15 16:44 459 查看
        参照下文字节码对应来看,环境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"


附注:

        如有错漏,烦请不吝指正,谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息