Is this a JVM bug or "expected behavior"?

JavaJvmCompiler OptimizationInteger Overflow

Java Problem Overview


I noticed some unexpected behavior (unexpected relative to my personal expectations), and I'm wondering if something if there is a bug in the JVM or if perhaps this is a fringe case where I don't understand some of the details of what exactly is supposed to happen. Suppose we had the following code in a main method by itself:

int i;
int count = 0;
for(i=0; i < Integer.MAX_VALUE; i+=2){
  count++;
}
System.out.println(i++);

A naive expectation would be that this would print Integer.MAX_VALUE-1, the largest even representable int. However, I believe integer arithmetic is supposed to "rollover" in Java, so adding 1 to Integer.MAX_VALUE should result in Integer.MIN_VALUE. Since Integer.MIN_VALUE is still less than Integer.MAX_VALUE, the loop would keep iterating through the negative even ints. Eventually it would get back to 0, and this process should repeat as an infinite loop.

When I actually run this code, I get non-deterministic results. The result that gets printed tends to be on the order of half a million, but the exact value varies. So not only is the loop terminating when I believe it should be an infinite loop, but it seems to terminate randomly. What's going on?

My guess is that this is either a bug in the JVM, or there is a lot of funky optimization going on that makes this expected behavior. Which is it?

Java Solutions


Solution 1 - Java

Known bug. Related to

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6196102

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6357214

and others.

I think they're considered low-priority to fix because they don't come up in the real world.

Solution 2 - Java

This is bizarre. It certainly looks like a bug somewhere. I get the same results every time with the same code, but trivial changes to the code change the result. For example:

public class Test {
  public static void main(String[] args) {
    int i;
    int count = 0;
    for (i = 0; i < Integer.MAX_VALUE; i+=2) {
      count++;
    }
    System.out.println(i);
    System.out.println(i < Integer.MAX_VALUE);
  }
}

... always prints 2147483640 and true

whereas this:

public class Test {
  public static void main(String[] args) {
    int i;
    for (i = 0; i < Integer.MAX_VALUE; i+=2) {
    }
    System.out.println(i);
    System.out.println(i < Integer.MAX_VALUE);
  }
}

always prints -2147483648 and true.

Very, very weird.

(That's running an OpenJDK 1.6 VM on Linux.)

EDIT: Running OpenJDK 1.7 on Windows 7, I don't see the problem:

java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b78)
Java HotSpot(TM) Client VM (build 17.0-b05, mixed mode, sharing)

Solution 3 - Java

Try adding System.out.println(count);

I wonder if there is optimization occurring because count is never read from.

Edit - another answer gave the link to bugs in Oracle's bug tracker. Drawing from that:

  • 6196102 in particular mentions that there is a canonicalization bug where Integer.MAX_VALUE is concerned.
  • Java must be trying to optimize the loop because count is never read from.

However, this is unlikely to occur in practice, because:

  • Integer.MAX_VALUE is an unlikely loop guard

  • Usually loops do work that wouldn't allow this optimization in the first place

Solution 4 - Java

This seems to be a loop optimizations as I observe the same result but IF I also print out count then the result changes.

I.e.

    int i;
    int count = 0;
    for(i=0; i < Integer.MAX_VALUE; i+=2){
      count++;
    }
    System.out.println(count);
    System.out.println(i++);

Produces 2147483638 while the original code produces 457158 (or similar)

Solution 5 - Java

java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode, sharing)

working as expected. infinite loop

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichael McGowanView Question on Stackoverflow
Solution 1 - JavaKevin BourrillionView Answer on Stackoverflow
Solution 2 - JavaJon SkeetView Answer on Stackoverflow
Solution 3 - JavaMatthew WillisView Answer on Stackoverflow
Solution 4 - JavaKrisView Answer on Stackoverflow
Solution 5 - JavajmjView Answer on Stackoverflow