(解決)64ビット版Java仮想マシンのおかしな振る舞い(整数編)


1.7.0ではこの現象は発生しませんでした。よかった。

64ビット版Java仮想マシンは、整数がオーバーフローする(可能性がある?)場合に、おかしな振る舞いをするようです。

例1

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6980767で報告されている例です。

public class Bug1 {

  public static void main(String[] args) {
    System.out.println(System.getProperty("java.runtime.version"));
    int foobar = Integer.MAX_VALUE;
    for (int value = 0; value <= foobar; value++) {
      if (value % 100000000 == 0) {
        System.out.println("At " + value);
      }
    }
    System.out.println("DONE");
  }
}

私の環境では、次のような実行結果になりましたが、これは適切なものではありません。

1.6.0_22-b04
At 0
DONE

ちなみに、32ビット版Java仮想マシンなら適切な結果になります。(略)

例2

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6979077で報告されている例です。

public class Bug2 {

  public static void main(String[] args) {
    System.out.println(System.getProperty("java.runtime.version"));
    for (int i = 0; i < 20; i++) {
      work(2147463647, Integer.MAX_VALUE);
    }
  }

  static void work(int l, int u) {
    int runs = 0;
    for (int i = l; (0 < i) && (i <= u); i++) {
      runs++;
    }
    System.out.println(runs);
  }
}

私の環境では、次のような実行結果になりましたが、これは適切なものではありません。

1.6.0_22-b04
20001
20001
20001
20001
20000
1025
1025
1025
1025
1025
1025
1025
1025
1025
1025
1025
1025
1025
1025
1025

ちなみに、32ビット版Java仮想マシンなら適切な結果になります。(略)

例3

フェルマーの最終定理の「反例」(C言語編)で紹介した例は、Javaでも有効なはず、つまりフェルマーの最終定理の反例を間違って表示して終了するはずですが、以下のコードは65ビット版Java仮想マシンでは止まりません(数学的には正しいけれど)。

public class Bug3 {

  public static void main(String[] args) {
    System.out.println(System.getProperty("java.runtime.version"));
    for (int c = 1; true; c++) {
      for (int a = 1; a < c; a++) {
        for (int b = a; b < c; b++) {
          if (a * a * a + b * b * b == c * c * c) {
            System.out.println("a = " + a + ", b = " + b + ", c = " + c);
            System.exit(0);
          }
        }
      }
    }
  }
}

「true」を「c < Integer.MAX_VALUE」に変えると適切な結果になります。

ちなみに、32ビット版Java仮想マシンなら適切な結果になります。(略)

どういうことなのかわかる人がいたら教えてほしいです。原因がわかるまでは、64ビット版Java仮想マシンは、ちょっとこわくて使えません。

1.6.0_26-b03でも確認しました。32ビット版は大丈夫で64ビット版はおかしいです。