2011-08-12 25 views
9

私はアプリケーションでクラスローダーのリークに取り組んでおり、最終的にCLへのすべての参照がなくなったということになりました。私のメモリプロファイリングツール(YourKitとjmap/jhatを使用)では、時々すぐにクラスローダーを取り除くGCを強制することができますが、それ以外の時間(アプリケーションの使用状況にもよりますが、 GC、CLインスタンスは消えません。私は、メモリスナップショットをキャプチャし、結果を見て、それはこのオブジェクトが存在するが、到達不能であると言います。到達不能なオブジェクトをGCするのにJVMを長く使うのはなぜですか?

ここは変わった部分です...私はこれを偶然発見しました。

私は完全にGCを強制することができますが、インスタンスは離れません。しかし、10〜20分後にもう一度完全なGCを実行すると、になります。うまくいけば

(この間アプリケーションは)ない全く(ほとんどは非アクティブです。私の「拡張」のコーヒーブレークは、この発見につながった事故だった。)

だからここにリークについての私の懸念は消えました( )、しかし問題は今、この振る舞いを説明しようとしています。

Sun JVMが到達不能なクラスローダーを20分間収集しないことを知っている人は誰でも知っていますか?

日JVMのバージョンの詳細:クラスローダ(とクラス:

java version "1.6.0_23" 
Java(TM) SE Runtime Environment (build 1.6.0_23-b05) 
Java HotSpot(TM) 64-Bit Server VM (build 19.0-b09, mixed mode) 
+0

これが役に立つかもしれません。情報のhttp://java.sun.com/developer/technicalArticles/javase/finalization/ – Jeremy

+0

つ以上のビットは、おそらく関連している:私はここで、並列コレクタを使用しています。 – Scott

+0

私の経験はあなたのものと全く同じであり、私はいつも正しいGCが達成するために複雑な方法でしか説明できません。それに関する興味深い「ディスカッション」はここにあります:http://stackoverflow.com/questions/176745/circular-references-in-java。 は、ガベージコレクタ、一つであるクラスローダー、弱参照であるanothersで扱ういくつかの特別な場合があります。実際のGCソースコードや_proven_答えを読んでこれを証明しようとしたら、ここに投稿してください。詳細にJava5でGCを議論する別の記事:http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html –

答えて

0

そうなJVMただの推測をgenerationalガベージコレクションを使用しますが、最終的にはフルマークアンドスイープに

+0

私はPS MarkSweep大きなを見て、用語の意味を理解していないよいない限りコレクションカウンタのインクリメント(およびその結果としてのテンポラルジェネレーションヒープの使用量の低下)は、私がそれを求めたときに完全な掃引が発生したことを示すように思えます。 GC'in CLのための私達の必要性をoversimplifyingのリスクが – Scott

0

を行うだろうので、ロードされている)は、通常のヒープにはなく、永続的な世代(PermGen)にあります。通常の状態では、クラスローダーが範囲外にならないので、メモリのこの部分は他のものよりもずっと少ない頻度でスワイプされます。

(この頻度に影響するいくつかのGC設定オプションがあるかもしれません)。私は、PermGenを塗りつぶしてそこにコレクションをトリガーすると思いますが、通常はこれをしたくありません。

実際にあなたのクラスローダーを収集する必要があるのはなぜですか?

+0

、コード、構成、およびその他のリソースに貢献アプリケーションに来て、行くことができる「プラグイン可能モジュールは、」そこにあります。これらのモジュールには特別なクラスローダーを作成して使用して要件を達成していますが、モジュールが移行すると、permgenなど、消費したメモリを再利用したいと考えています。 – Scott

+0

新しいモジュールがこのスペースを必要とするときはいつでも消え去りそうですが、私はそのような動的モジュールシステムについての経験はありませんでした。 –

5

私はジェレミー・ヘイラーがファイナライズ上の問題で正しいトラックにいると思います。基本的には、GCが到達不能であることが分かっていても、オブジェクトが実際に収集されるまでにはまだ不確定な時間である可能性があります。ファイナライザスレッドは、オブジェクトをファイナライズするために回り込む必要があります(ファイナライズする必要がある他のオブジェクトの数とファイナライザの外観によっては時間がかかることがあります)。オブジェクトがファイナライズされた後は、 別の GCは、オブジェクトが実際に収集される前に到達不能であることを再発見します。

さらに、Sun JVM上のClassLoaderの場合、PermGenに直接割り当てられている可能性があります。ですから、2個の完全なPermGenスイープ(1つはオブジェクトをファイナライゼーションキューに入れてから、もう1つは実際にそれを収集する)です。 PermGen掃引は高価なので、Sun JVMはデフォルト設定ではまったく実行しないと思います。さまざまなGCチューニングを行っても、PermGenを掃除するのは非常に嫌です(特に、 )。

そうではなく、あなたが何かを行う場合は、何 System.gc()を使用してGC(ええと、私は意味、 を奨励)強制の:もちろん

System.gc(); 
System.runFinalization(); 
System.gc(); 

を、でもこれは動作が保証されていませんが、大規模なファイナライズが必要なオブジェクトをクリーンアップするためには、少なくとも最小限の作業を行います。

+0

正しいかもしれませんが、私が見ていると思われる非決定的な振る舞いを考えると、それを証明することはできません。結局、私のCLは収集され、私はpermgenの使用量の低下を見ることもできます。これは良いことです。私はちょうどそれが戻って来て、生産の問題から後で私をかむかもしれないとき、特に非決定論的な行動が好きではありません! :) – Scott

+0

@Scott:残念ながら、真のガベージコレクションは常に非決定論的です。あなたはそれについて本当に何もできません。あなたが本当に確定的な動作が必要な場合は、[リアルタイムのJava](http://en.wikipedia.org/wiki/Real-time_specification_for_Java)になっているはずです。 –

0

可能な理由は、クラスローダをソフト参照によって保持されたことです。

-XX:SoftRefLRUPolicyMSPerMB=1 

で実行してみてください、それは違いを作るかどうかを確認します。それはmy caseで起こったことです。

関連する問題