2011-02-11 12 views
1

私はこの非常にメモリ集約型のJavaアプリケーションを構築しており、数百万のノードのツリーを構築しています。以下に示すように、ヒープ情報を取得するための便利なダンディランタイムメソッドを使用して、私は、現在のメモリ使用量を表示するちょっといい方法を構築しました:Javaのガベージコレクションの問題

public void displayMemoryUsage() { 
    long maxMem = Runtime.getRuntime().maxMemory(); 
    long freeMem = Runtime.getRuntime().freeMemory(); 
    long heapMem = Runtime.getRuntime().totalMemory(); 
    long usedMem = heapMem - freeMem; 
    System.out.println("Memory used: " + (int) (usedMem * 100/maxMem) + "%"); 
} 

だからそれをテストするために、私は木がそのルートノードを展開していました(2128人の子供に)、その後それらの子供のそれぞれを拡大した(ツリー内の合計約400万のノード)。メモリは使用された11%を表示します。次に、ツリーのルートをルートの子の1つに設定し、そうすることでルートの他の子への参照をすべて削除します。理論的には、元のルートの子要素の2127/2128が削除されます。強制ガベージコレクションのためにJavaのRuntime.getRuntime()。gc()メソッドを実行し、メモリ使用量を再度表示するように指示しました。今回は、私は10%を得ました。理論的には、この新しいパーセンテージは、新しいルートを設定する前の値の0.05%、つまり1/2128にはならないでしょうか?

ごみが適切に拾われない理由は何ですか?

+6

ごめんなさいニックピッカーですが、ガベージコレクションを強制することはできません。そうするには、JVMに_suggest_するだけです。 http://download.oracle.com/javase/6/docs/api/java/lang/Runtime.html#gc%28%29 – Nishant

+0

@Nishant:APIの実際の効果が著しく誤解されている場合、それは慎重ではありません。 –

答えて

4

System.gc(および同等Runtime.gc)メソッドは、ガベージコレクションされるべきであるガベージコレクタへ提案であるので、「ガベージコレクション強制」しない真の方法:Javaから

System.gcメソッドのAPI仕様:

ガベージコレクタを実行します。 GCメソッドの呼び出し

は Java仮想マシンが、彼らは現在、迅速 再利用可能な占有 メモリを作る ために使用されていないオブジェクトのリサイクルに向けた努力 を費やすことを示唆しています。 * メソッド呼び出しから制御が戻ると、Java仮想マシン は、破棄されたすべてのオブジェクトから スペースを再利用するために最善を尽くしました。

(強調は追加。)

をさらに、専門的の少し上で、ガベージコレクションが行われなかった場合でも、Java仮想マシン上に存在する他のオブジェクトが存在することに注意してくださいあなたのプログラムとは別に、そこからいくらかのメモリオーバーヘッドが生じるでしょう。

あなたのツリーがどれくらいのメモリを占有しているかを実際に把握するには、ツリーの作成前後でメモリ使用量をチェックする方法がありますが、あなたのツリーが構築されている間、それで完璧なメトリックになることはありません。

おそらく最も良いオプションは、実際にヒープがどれだけ使用されているかを実際に調べるためのプロファイラ(JDKに付属のjvisualvmなど)を使用することです。

0
  1. 削除されたノードへの参照はどこにもありませんか?
  2. gc()の後に十分に待っていますか(複数回提案しましたか?
1

代わりにアプリケーションのプロファイルを作成してください。