这是JVM错误还是“预期行为”?

时间:2011-03-03 16:21:04

标签: java jvm compiler-optimization integer-overflow

我注意到了一些意想不到的行为(相对于我的个人期望而出乎意料),我想知道JVM中是否存在错误,或者这是否是一个我不了解某些细节的边缘情况应该发生什么。假设我们在main方法中有以下代码:

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

一个天真的期望是,这将打印Integer.MAX_VALUE-1,最大甚至可表示int。但是,我认为整数算术应该在Java中“翻转”,因此向Integer.MAX_VALUE添加1会导致Integer.MIN_VALUE。由于Integer.MIN_VALUE仍然小于Integer.MAX_VALUE,因此循环将继续迭代负数甚至整数。最终它会回到0,这个过程应该重复为无限循环。

当我实际运行此代码时,我得到了非确定性结果。打印的结果往往大约为50万,但确切的值会有所不同。因此,当我认为它应该是一个无限循环时,不仅循环终止,而且它似乎随机终止。发生了什么事?

我的猜测是,这可能是JVM中的一个错误,或者正在进行大量的时髦优化,这会产生这种预期的行为。这是什么?

5 个答案:

答案 0 :(得分:48)

已知错误。与

相关

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

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

和其他人。

我认为它们被认为是低优先级的,因为它们不会出现在现实世界中。

答案 1 :(得分:15)

这很奇怪。它当然看起来像一个错误。每次使用相同的代码我都会得到相同的结果,但代码的微小变化会改变结果。例如:

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);
  }
}

...始终打印2147483640和true

而这:

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);
  }
}

始终打印-2147483648并且为真。

非常非常奇怪。

(那是在Linux上运行OpenJDK 1.6 VM。)

编辑:在Windows 7上运行OpenJDK 1.7,我没有看到问题:

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)

答案 2 :(得分:4)

尝试添加System.out.println(count);

我想知道是否存在优化,因为永远不会读取计数。

编辑 - 另一个答案给出了Oracle错误跟踪器中的错误链接。借鉴:

  • 6196102特别提到存在Integer.MAX_VALUE涉及的规范化错误。
  • Java必须尝试优化循环,因为永远不会读取count

然而,这在实践中不太可能发生,因为:

  • Integer.MAX_VALUE是一个不太可能的循环保护
  • 通常循环确实起作用,首先不允许这种优化

答案 3 :(得分:2)

这似乎是循环优化,因为我观察到相同的结果,但如果我也打印出count,那么结果会发生变化。

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

生成2147483638,而原始代码生成457158(或类似)

答案 4 :(得分:0)

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)

按预期工作。无限循环