6

Javaコードは次のとおりです。

Random r = new Random(1234697890);
HashMap<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
List<Integer> list = new ArrayList<Integer>();

for(int i=0;i<100000;i++){
    for(int j=0;j<1000;j++){
        list.add(r.nextInt(100000));
    }
    map.put(i, list);
    map.remove(i);
}

i37553に達すると、java.lang.OutOfMemoryError: Java heap space発生します。
ループ内でガベージコレクションが発生していないようです。
今、私は問題を解決する方法を考えています。

4

4 に答える 4

5

ループの終了時に 100000 * 1000 項目を含む同じリストを常に使用します。GC がリストを削除できるようにするには、スコープをfor(i)ループ内に縮小する必要があります。

つまり、マップとリストの両方がそのコードで常に到達可能であるため、コレクションの対象にはなりません。

于 2012-12-05T13:11:31.997 に答える
5

次のようにコードを書き直してみてください。OOME の問題は発生しないはずです...

Random r = new Random(1234697890);
HashMap<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();

for(int i=0;i<100000;i++){
    List<Integer> list = new ArrayList<Integer>();
    for(int j=0;j<1000;j++){
        list.add(r.nextInt(100000));
    }
    map.put(i, list);
    map.remove(i);
}

元のコードの問題は次のとおりです。

  • リストを 1 つだけ作成し、
  • そこにどんどん要素を追加し続け、
  • そのリストは、コードが完了したときにのみガベージになります...常に「スコープ内」にあるためです。

list宣言をループ内に移動するArrayListと、各ループ反復で新しいが作成されて埋められ、次の反復を開始するとガベージになります。


誰かが に電話することを提案しSystem.gc()ました。収集されるガベージ最小限であるため、あなたの場合はまったく役に立ちません。一般に、次の理由から、これは悪い考えです。

  • GC は、OOME がスローされる直前に実行されることが保証されます。
  • JVM は、GC を実行するのに最適な (つまり、最も効率的な) 時期をユーザーよりも正確に把握できます。
  • への呼び出しSystem.gc()はとにかく完全に無視される可能性があります。System.gc()への呼び出しが無視されるように JVM を構成できます。

1 - 私の衒学者は、ガベージになる可能性が最も高いオブジェクトをmap.put(i, list); map.remove(i);生成している可能性が最も高いことを指摘したいと思います。ただし、無限に成長するオブジェクトIntegerと比較すると、これは「鶏の餌」です。ArrayList

于 2012-12-05T13:19:44.560 に答える
0

あなたの場合、同じものを埋め続けますlist(その HashMap から削除しても、ローカル変数として存在します)。

JVM は、OutOfMemoryError. したがって、クリーンアップするものが何も残っていないことを確認できます。

于 2012-12-05T13:13:33.767 に答える
0

あなたのコード

List<Integer> list = new ArrayList<Integer>();

for(int i=0;i<100000;i++){
    for(int j=0;j<1000;j++){
        list.add(r.nextInt(100000));
    }
    map.put(i, list);
    map.remove(i);
}

と同じです

List<Integer> list = new ArrayList<Integer>();

for(int i=0;i<100000 * 1000; i++) {
    list.add(r.nextInt(100000));
}

ご覧のとおり、すべての整数を保持しているマップではなく、リストです。ところで、代わりにこれを試して、何が起こるか見てみましょう;)

list.add(r.nextInt(128));
于 2012-12-05T13:30:39.903 に答える