1. ホーム
  2. java

[解決済み] Java: int 型配列が 0 ではない要素で初期化される。

2022-07-09 18:42:49

質問

JLSによると int 配列は初期化直後にゼロで埋められるはずです。しかし、そうでない状況に直面しています。このような動作は、JDK 7u4で最初に発生し、それ以降のすべてのアップデートでも発生します(私は64ビット実装を使用しています)。次のコードは例外を投げます。

public static void main(String[] args) {
        int[] a;
        int n = 0;
        for (int i = 0; i < 100000000; ++i) {
            a = new int[10];
            for (int f : a)
                if (f != 0)
                  throw new RuntimeException("Array just after allocation: "+ Arrays.toString(a));
            Arrays.fill(a, 0);
            for (int j = 0; j < a.length; ++j)
                a[j] = (n - j)*i;
            for (int f : a)
                n += f;
        }
        System.out.println(n);
    }

この例外は、JVMがコードブロックのコンパイルを実行した後に発生します。 -Xint フラグでは発生しません。さらに Arrays.fill(...) 文は(このコード内の他のすべての文と同様に)必要であり、それがない場合は例外が発生しません。この可能性のあるバグは、何らかのJVMの最適化によって制限されていることは明らかです。このような動作の理由のための任意のアイデア?

更新しました。

Gentoo Linux, Debian Linux (both kernel 3.0 version) および MacOS Lion 上の HotSpot 64-bit server VM, Java version 1.7.0_04 から 1.7.0_10 でこの挙動が確認されました。このエラーは、上記のコードで必ず再現できます。32bitのJDKやWindowsではこの問題をテストしていません。私はすでにOracleにバグレポートを送信しており(バグID 7196857)、数日中に公開Oracleバグデータベースに表示される予定です。

更新しました。



Oracle 社は、このバグを公開バグデータベースで公開しました。 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7196857

どのように解決するのですか?

ここで、JITコンパイラのバグに直面します。コンパイラは、アロケートされた配列が Arrays.fill(...) の中でアロケートされた配列が満たされたと判断しますが、アロケートと充填の間の用途のチェックに欠陥があります。そのため、コンパイラは不正な最適化を実行し、割り当てられた配列のゼロ化をスキップしてしまいます。

このバグは Oracle のバグトラッカー ( バグID 7196857 ). 残念ながら、私は以下の点についてOracleからの説明を待たなかった。私の見るところ、このバグはOSに依存します。64ビットのLinuxとMacでは絶対に再現しますが、コメントで見るところ、Windowsでは(JDKの類似バージョンでは)定期的に再現しません。さらに、このバグがいつ修正されるかを知ることは良いことだと思います。

現時点で唯一のアドバイスは、新しく宣言された配列のために JLS に依存している場合、JDK1.7.0_04 またはそれ以降を使用しないことです。

10 月 5 日に更新しました。

新しい ビルド 10 で、このバグは少なくとも Linux OS では修正されています。このバグがOracleのバグデータベースで公開されていないことを発見してくれた@Makotoさんに感謝します。残念ながら、Oracleが公開を中止した理由は分かりませんが、Googleでは公開されています。 キャッシュ . また、このバグは Redhat の注意を引きました: CVE 識別子 CVE-2012-4420 ( バグジラ ) と CVE-2012-4416 ( バグジラ ) がこの欠陥に割り当てられていました。