70

予期しない動作(個人的な期待に比べて予期しない)に気づきました。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ループは負の偶数intを反復し続けます。最終的には0に戻り、このプロセスは無限ループとして繰り返されるはずです。

このコードを実際に実行すると、非決定論的な結果が得られます。印刷される結果は50万のオーダーになる傾向がありますが、正確な値は異なります。したがって、ループは無限ループであると私が信じるときに終了するだけでなく、ランダムに終了するように見えます。どうしたの?

私の推測では、これはJVMのバグであるか、この予想される動作を実現する多くのファンキーな最適化が行われていると思います。どっち?

4

5 に答える 5

48

既知のバグ。関連

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

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

その他。

現実の世界では出てこないので、修正の優先度は低いと考えられていると思います。

于 2011-03-03T16:44:56.093 に答える
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とtrueを出力します。

とても、とても奇妙です。

(Linux上でOpenJDK 1.6 VMを実行しています。)

編集:Windows7でOpenJDK1.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)
于 2011-03-03T16:30:31.640 に答える
4

追加してみてくださいSystem.out.println(count);

カウントが読み取られないため、最適化が行われているのではないかと思います。

編集-別の回答は、Oracleのバグトラッカーのバグへのリンクを提供しました。それからの描画:

  • 6196102は特に、懸念される正規化のバグがあると述べていInteger.MAX_VALUEます。
  • countから読み取られることはないため、Javaはループを最適化しようとしている必要があります。

ただし、これは実際には発生しない可能性があります。理由は次のとおりです。

  • Integer.MAX_VALUEありそうもないループガードです
  • 通常、ループは、そもそもこの最適化を許可しない動作をします。
于 2011-03-03T16:27:49.297 に答える
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++);

元のコードが457158(または同様のもの)を生成するのに対し、2147483638を生成します

于 2011-03-03T16:37:23.257 に答える
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)

期待どおりに動作します。無限ループ

于 2011-03-03T17:26:25.800 に答える