I observed erroneous behaviour running the following java-code:
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); } } }
Both loops do exactly the same. Nevertheless, the second one outputs a non-deterministic erroneous value. I'm running the code on Linux using Version:
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)
Sample Output:
1073741811 141312
Can you reproduce it? Is it a bug?
Edit: Strange
final int end = Integer.MAX_VALUE - 1;
works fine.
Looping in Java Java provides three repetition statements/looping statements that enable programmers to control the flow of execution by repetitively performing a set of statements as long as the continuation condition remains true. These three looping statements are called for, while, and do… while statements.
In computer programming, loops are used to repeat a block of code. For example, if you want to show a message 100 times, then rather than typing the same code 100 times, you can use a loop. In Java, there are three types of loops.
Therefore, in this basic example, a Repeat loop is the better choice.
I'm able to reproduce it with the .class
file produced by Eclipse, but not when compiling on the command line with javac
.
The bytecode generated differs:
javac
outputpublic 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
For something easier to read, here is the Grimp output produced by 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;
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
Grimp output:
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;
Interestingly, the javac
-produced version uses if_icmpge
as an exit condition (>= 2147483647) on an int
, which shouldn't make sense (the equal does, but not the greater than). Both look correct, though, so I'd suspect a JVM bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With