Я могу воспроизвести его с помощью файла .class
, созданного Eclipse, но не при компиляции в командной строке с javac
.
Сгенерированный байт-код отличается:
javac
output
public static void main(java.lang.String[]);
Code:
0: lconst_0
1: lstore_3
2: ldc #2; //int 1073741823
4: istore 5
6: iload 5
8: ldc #3; //int 2147483647
10: if_icmpge 23
13: lload_3
14: lconst_1
15: ladd
16: lstore_3
17: iinc 5, 1
20: goto 6
23: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
26: lload_3
27: invokevirtual #5; //Method java/io/PrintStream.println:(J)V
30: lconst_0
31: lstore_3
32: ldc #2; //int 1073741823
34: istore 5
36: iload 5
38: ldc #3; //int 2147483647
40: if_icmpge 53
43: lload_3
44: lconst_1
45: ladd
46: lstore_3
47: iinc 5, 1
50: goto 36
53: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
56: lload_3
57: invokevirtual #5; //Method java/io/PrintStream.println:(J)V
60: return
Для простоты чтения приведем вывод Grimp, производимый Soot :
java.lang.String[] r0;
long l0, l2;
int i1, i3;
r0 := @parameter0;
l0 = 0L;
i1 = 1073741823;
label0:
if i1 >= 2147483647 goto label1;
l0 = l0 + 1L;
i1 = i1 + 1;
goto label0;
label1:
java.lang.System.out.println(l0);
l2 = 0L;
i3 = 1073741823;
label2:
if i3 >= 2147483647 goto label3;
l2 = l2 + 1L;
i3 = i3 + 1;
goto label2;
label3:
java.lang.System.out.println(l2);
return;
Выход компилятора Eclipse
public static void main(java.lang.String[]);
Code:
0: ldc #16; //int 1073741823
2: istore_1
3: ldc #17; //int 2147483647
5: istore_2
6: lconst_0
7: lstore_3
8: ldc #16; //int 1073741823
10: istore 5
12: goto 22
15: lload_3
16: lconst_1
17: ladd
18: lstore_3
19: iinc 5, 1
22: iload 5
24: ldc #17; //int 2147483647
26: if_icmplt 15
29: getstatic #18; //Field java/lang/System.out:Ljava/io/PrintStream;
32: lload_3
33: invokevirtual #24; //Method java/io/PrintStream.println:(J)V
36: lconst_0
37: lstore_3
38: ldc #16; //int 1073741823
40: istore 5
42: goto 52
45: lload_3
46: lconst_1
47: ladd
48: lstore_3
49: iinc 5, 1
52: iload 5
54: ldc #17; //int 2147483647
56: if_icmplt 45
59: getstatic #18; //Field java/lang/System.out:Ljava/io/PrintStream;
62: lload_3
63: invokevirtual #24; //Method java/io/PrintStream.println:(J)V
66: return
Выходное сжатие:
java.lang.String[] r0;
int i0, i1, i3, i5;
long l2, l4;
r0 := @parameter0;
i0 = 1073741823;
i1 = 2147483647;
l2 = 0L;
i3 = 1073741823;
goto label1;
label0:
l2 = l2 + 1L;
i3 = i3 + 1;
label1:
if i3 < 2147483647 goto label0;
java.lang.System.out.println(l2);
l4 = 0L;
i5 = 1073741823;
goto label3;
label2:
l4 = l4 + 1L;
i5 = i5 + 1;
label3:
if i5 < 2147483647 goto label2;
java.lang.System.out.println(l4);
return;
Интересно, что javac
-производимая версия использует if_icmpge
в качестве условия выхода (> = 2147483647) для int
, что не должно делатьсмысл (равенство делает, но не больше чем).И то и другое выглядит правильно, поэтому я подозреваю, что ошибка JVM.