【问题标题】:Is this a JVM bug or "expected behavior"?这是 JVM 错误还是“预期行为”?
【发布时间】:2011-07-08 04:41:35
【问题描述】:

我注意到一些意外行为(相对于我个人的期望而言是意外的),我想知道是否 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 中“翻转”,所以将 1 加到 Integer.MAX_VALUE 应该会导致 Integer.MIN_VALUE。由于Integer.MIN_VALUE 仍然小于Integer.MAX_VALUE,因此循环将继续遍历负偶数整数。最终它会回到 0,并且这个过程应该以无限循环的形式重复。

当我实际运行这段代码时,我得到了不确定的结果。打印出来的结果往往是 50 万左右,但确切的值会有所不同。因此,当我认为它应该是一个无限循环时,循环不仅会终止,而且它似乎是随机终止的。怎么回事?

我的猜测是,这要么是 JVM 中的错误,要么是正在进行的许多时髦优化导致了这种预期行为。是哪个?

【问题讨论】:

  • 这就是你的主要方法中的全部内容吗?
  • @Michael:只是检查一下没有发生一些时髦的线程。在我的机器上它总是打印出 2147483640,但这仍然出乎意料。
  • 我试了 3 次,结果在 300,000 和 500,000 之间 - 所以看起来它是特定于 VM 的(build 1.6.0_24-b07, 32bit linux)
  • 程序永远不会在带有 HotSpot 1.6.0_24 的 32 位 Windows XP 上终止
  • Java 从未停止让我惊叹。对 OP +1 和对链接到 Oracle/Sung 错误的答案 +1。我最近最喜欢的是这个:stackoverflow.com/questions/4949057 :)

标签: java jvm compiler-optimization integer-overflow


【解决方案1】:

已知错误。相关

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

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

和其他人。

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

【讨论】:

    【解决方案2】:

    这很奇怪。它肯定在某处看起来像一个错误。我每次使用相同的代码都会得到相同的结果,但是对代码的微小更改会改变结果。例如:

    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 和 true。

    非常非常奇怪。

    (在 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)
    

    【讨论】:

      【解决方案3】:

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

      我想知道是否发生了优化,因为从不读取计数。

      编辑 - 另一个答案提供了 Oracle 错误跟踪器中错误的链接。从中汲取灵感:

      • 6196102 特别提到了与 Integer.MAX_VALUE 相关的规范化错误。
      • Java 必须尝试优化循环,因为从未读取过 count

      但是,这在实践中不太可能发生,因为:

      • Integer.MAX_VALUE 不太可能是循环保护
      • 通常循环的工作一开始就不允许这种优化

      【讨论】:

      • 这至少使我的测试运行一致。所以这是一个优化问题?
      【解决方案4】:

      这似乎是一个循环优化,因为我观察到相同的结果,但如果我也打印出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(或类似)

      【讨论】:

        【解决方案5】:
        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)
        

        按预期工作。无限循环

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-03
          • 2019-08-11
          • 2015-07-25
          • 2011-07-30
          相关资源
          最近更新 更多