Влияет ли try..catch.. на производительность в конце концов?
Эксперимент 1: простое понимание
Просто напишите простую программу
public class Test {
public static void main(String[] args) {
int a = 0,b=2;
try {
a = b/0;
}catch (Exception e){
a = 1;
}
}
}
Взгляните на процесс инструкции байт-кода:
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. Видно, что если код не ошибается, производительность почти не меняется, и она такая же, как при обычном выполнении кода.
Какова концепция времени обработки исключений?
Эксперимент 2: длительный тест обработки исключений
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.
Прежде чем я изменил его (запуск без исключения), результат запуска1133После модификации (будет исключение деления на 0) текущий результат44177
Конечно, этот результат связан с вычислительной мощностью процессора, и результаты многократных прогонов почти одинаковы.
Поэтому видно, что когда программа попадает в ловушку, она очень ресурсоемка.
Затем попробуйте поймать снаружи или внутри цикла for, что лучше?
Эксперимент 3: цикл 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
Эксперимент 4: попытка находится вне цикла for
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
Объединив третий и четвертый эксперименты, мы обнаружили, что можно сказать, что производительность обоих одинакова с точки зрения времени выполнения и инструкций байт-кода. Нет ничего страшного в том, что вы считаете, что размещение кода try в цикле for будет излишним и удвоит потребление ресурсов.
Но с точки зрения логики выполнения они немного отличаются.В эксперименте 3, поскольку for находится в try catch, jvm помещает обработку исключений после цикла for при компиляции. который:第24-27行; В эксперименте 4 обработка исключений находится внутри цикла for, а именно:第18-22行. Почти такой же.
Вышеупомянутое является только личной тестовой точкой зрения, если есть какая-либо ошибка, пожалуйста, оставьте сообщение ниже, спасибо!