[英]Erroneous for-loops in Java?
我观察到运行以下java代码的错误行为:
public class Prototype {
public static void main(String[] args) {
final int start = Integer.MAX_VALUE/2;
final int end = Integer.MAX_VALUE;
{
long b = 0;
for (int i = start; i < end; i++) {
b++;
}
System.out.println(b);
}
{
long b = 0;
for (int i = start; i < end; i++) {
b++;
}
System.out.println(b);
}
}
}
两个循环完全相同。 然而,第二个输出非确定性的错误值。 我正在使用Version在Linux上运行代码:
java version "1.6.0_25"
Java(TM) SE Runtime Environment (build 1.6.0_25-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.0-b11, mixed mode)
样本输出:
1073741811
141312
你能重现吗? 这是一个错误吗?
编辑:奇怪
final int end = Integer.MAX_VALUE - 1;
工作良好。
我能够使用Eclipse生成的.class
文件重现它,但不能在使用javac
在命令行上进行javac
时重现它。
生成的字节码不同:
javac
输出 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
对于更容易阅读的内容,这里是Soot生成的Grimp输出:
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;
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
生成的版本在int
上使用if_icmpge
作为退出条件(> = 2147483647),这应该没有意义(等于,但不是大于)。 但两者看起来都是正确的,所以我怀疑是一个JVM错误。
当上限接近Integer.MAX_VALUE
时,存在影响for循环的错误。
看到这个问题 。
有可能是在64位服务器VM中的HotSpot中展开错误的循环。 尝试使用-client
或+XX:-AggressiveOpts
运行代码+XX:-AggressiveOpts
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.