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ビット版はおかしいです。