try..catch..到底影響性能嗎?java
隨便寫一個簡單的程序bash
public class Test {
public static void main(String[] args) {
int a = 0,b=2;
try {
a = b/0;
}catch (Exception e){
a = 1;
}
}
}
複製代碼
看一下字節碼指令過程:jvm
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: iconst_0 push 0
1: istore_1 pop並保存到局部變量1
2: iconst_2 push 2
3: istore_2 pop並保存到局部變量2
4: iload_2 從局部變量裏拿出並push
5: iconst_0 push 0
6: idiv 棧頂兩數相除
7: istore_1
8: goto 14
11: astore_3
12: iconst_1
13: istore_1
14: return
Exception table:
from to target type
4 8 11 Class java/lang/Exception
LineNumberTable:
line 8: 0
line 10: 4
line 13: 8
line 11: 11
line 12: 12
line 14: 14
LocalVariableTable:
Start Length Slot Name Signature
12 2 3 e Ljava/lang/Exception;
0 15 0 args [Ljava/lang/String;
2 13 1 a I
4 11 2 b I
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 11
locals = [ class "[Ljava/lang/String;", int, int ]
stack = [ class java/lang/Exception ]
frame_type = 2 /* same */
}
複製代碼
能夠看到有個異常表:性能
Exception table:
from to target type
4 8 11 Class java/lang/Exception
複製代碼
from
表示try catch
的開始地址 to
表示try catch
的結束地址 target
表示異常的處理起始位 type
表示異常類名稱測試
代碼運行時出錯時,會先判斷出錯位置是否在from - to
的範圍,若是是,則從target
標誌位往下執行,若是沒有出錯,直接goto
到return
。能夠看出,若是代碼不出錯的話,性能幾乎是不受影響的,和正常的代碼執行是同樣的。ui
那異常處理耗時是什麼個概念呢?spa
public class Test {
public static void main(String[] args) {
int a = 0,b=2;
long startTime = System.nanoTime();
for (int i = 10; i>0;i--){
try {
a = b/i;
}catch (Exception e){
a = 1;
}finally {
}
}
long runTime = System.nanoTime()-startTime;
System.out.println(runTime);
}
}
複製代碼
我只須要把i>0
改爲i>=0
,程序遍會進行一次異常處理,由於除數不能爲0.code
我在修改以前(無異常運行),運行的結果是1133
修改以後(會出現除數爲0異常),運行結果是44177
ip
固然,這個結果和cpu的算力有關,屢次運行結果相差無幾。資源
因此,能夠看出一旦程序進入到catch裏,是很是耗資源的。
那try catch 在for循環外面或者裏面,哪一個更好呢?
public class Test {
public static void main(String[] args) {
int a = 0,b=2;
long startTime = System.nanoTime();
try {
for (int i = 10; i>=0;i--){
a = b/i;
}
}catch (Exception e){
a = 1;
}finally {
long runTime = System.nanoTime()-startTime;
System.out.println(runTime);
}
}
}
複製代碼
運行屢次的控制檯輸出:
46820 48708 54749 47953 46820 45310
複製代碼
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=5, args_size=1
0: iconst_0
1: istore_1
2: iconst_2
3: istore_2
4: bipush 10
6: istore_3
7: iload_3
8: iflt 21
11: iload_2
12: iload_3
13: idiv
14: istore_1
15: iinc 3, -1
18: goto 7
21: goto 35
24: astore_3
25: iconst_1
26: istore_1
27: goto 35
30: astore 4
32: aload 4
34: athrow
35: return
Exception table:
from to target type
4 21 24 Class java/lang/Exception
4 21 30 any
24 27 30 any
30 32 30 any
複製代碼
public class Test {
public static void main(String[] args) {
int a = 0,b=2;
long startTime = System.nanoTime();
for (int i = 10; i>=0;i--){
try {
a = b/i;
}catch (Exception e){
a = 1;
}finally {
}
}
long runTime = System.nanoTime()-startTime;
System.out.println(runTime);
}
}
複製代碼
控制檯打印:
42289 47953 49463 45688 45310
複製代碼
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=6, args_size=1
0: iconst_0
1: istore_1
2: iconst_2
3: istore_2
4: bipush 10
6: istore_3
7: iload_3
8: iflt 36
11: iload_2
12: iload_3
13: idiv
14: istore_1
15: goto 30
18: astore 4
20: iconst_1
21: istore_1
22: goto 30
25: astore 5
27: aload 5
29: athrow
30: iinc 3, -1
33: goto 7
36: return
Exception table:
from to target type
11 15 18 Class java/lang/Exception
11 15 25 any
18 22 25 any
25 27 25 any
複製代碼
綜合實驗三和實驗四,咱們發現不管從運行時長仍是從字節碼指令的角度看,它兩的性能能夠說是同樣的。並無你感受到的for循環裏放try代碼會冗餘、資源消耗加倍的問題。
可是從運行邏輯來看,兩個是有點不一樣的,實驗三中,由於for在try catch裏,因此jvm在編譯的時候,把異常處理放在for循環後面才進行。即:第24-27行
;實驗四中,異常處理是在for循環內部的,即:第18-22行
。大同小異。
以上僅我的測試觀點,若是有誤請在下方留言,謝謝!