1

私はJavaとそのメモリリークを許容する能力について少し実験を行っています。私はこの簡単なコードを書きました:

import java.util.ArrayList;
import java.util.List;

public class Test {

public static void main(String[] args) {

    class Obj {
        int i;

        Obj(int i) {
            this.i = i;
        }
    }

    List<Obj> list;
    while(true) {
        list = new ArrayList<Obj>();
        for(int i = 0; i < 1000; i++) {
            Obj o = new Obj(i);
            list.add(o);
        }

        try {
            Thread.sleep(1); //<-- added to give the gc time to trash the previous iteration
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}

これを実行すると(特に、反復ごとにリストに追加されるオブジェクトが増えると)、使用されるメモリの量が急速に増加するのを確認できます。反復ごとに10000個のオブジェクトが追加され、2ギガバイトにすばやく到達することができました。リスト(および関数のような「リンクリスト」リストを利用する他のタイプのオブジェクト)は削除されたくないように見えます。

オブジェクトをリストに追加しなかった場合、メモリヒープはまったく増加しませんでした(つまり、ごみ処理がその役割を果たしていました)。反復ごとにリストをnullにリセットしてから、リストを再宣言し、clear()メソッドを呼び出してみました。何も機能していないようです。ループでリストを使用するときはいつでも、RAMが助けを求めて叫びます。

では、なぜこれが発生するのでしょうか。なぜゴミ処理は、リストを積み上げるのではなく、反復ごとにリストを削除しないのですか?リストインターフェイスでは、この種の使用は許可されていませんか?最後のインスタンスを取り除くのに十分な時間をゴミ処理に与えていないだけですか?

4

4 に答える 4

5

あなたのコードは大丈夫です。JVMでいくつかのあいまいな、そしてまれなバグに遭遇しない限り、メモリリークもありません。発生する可能性が高いのは、JVMに多くのメモリを割り当てて、そのメモリを使用することにしたことです。

コードを試してみましたが、表示されているものを再現できる唯一の方法は、非常に大きな若い世代のヒープを構成することです(-Xmn)。JVMは、若い世代がいっぱいになるまでガベージコレクターを実行する必要がないため、プロセスはかなりの量のメモリを使用することになります。

ただし、若い世代のヒープがいっぱいになると、GCが実行され、到達不能なオブジェクトがすべて収集されます。

次のスクリーンショットでは、右上のグラフがヒープサイズを示しています。

VisualVM

ご覧のとおり、19:47:50の直前に大幅な低下が見られます。これは、若い世代がいっぱいになり、GCが実行され、すべての古いリストが収集されたときです。

OSツールを使用してメモリ使用量を監視している場合、ガベージコレクターの実行時に低下が見られない可能性があることに注意してください。一部のヒープオブジェクトが解放されると、それらが占有していたメモリは通常、OSに解放されません。ただし、同じプロセスで再利用できます。

メモリ使用量が問題になる場合は、JVMに提供しているオプションを再検討する必要があります。

于 2013-03-12T19:51:15.587 に答える
0

ループ内のすべての反復の後にに設定listする必要があります。このようにして、GarbageCollectorは安全にクリーンアップできることを認識しました。nullwhile

また、これは動作に対処する可能性があります。http://docs.oracle.com/cd/E19159-01/819-3681/abebi/index.html

于 2013-03-12T19:52:09.210 に答える
0

(通常、コメントして設定したVMオプションを尋ねるだけですが、それを行うのに十分な担当者ポイントがありません)

推測しているだけですが、おそらく-Xmsを1GBに設定しますか?このコードはリークしませんが、VMオプションによっては、プロセスに大量のメモリが必要になる場合があります。

于 2013-03-12T19:57:16.250 に答える
0

コードにメモリリークはありません。あなたはそれについて100%確信することができます。ただし、これは、現在アクティブなすべてのオブジェクトがヒープよりも小さい場合でも、メモリが不足しないことを意味するものではありません。

自分のようなコードでガベージコレクションをテストすることはできません。GCは毎回呼び出されるわけではなく、すべてを一度にクリーンアップするわけではありません。大量のデータを高速で更新している場合、GCを起動する時間がなく、コードのメモリが不足している可能性があります。

また、メモリリークは、アプリケーションのメモリが不足しているかどうかを監視することではなく、プロファイリングツールを使用してテストされることを理解することも重要です。

于 2013-03-12T19:59:12.577 に答える