Java アプリケーションでメモリ リークを見つけたいのですが、Netbeans プロファイラーを使用してそれを行う方法がわかりません。
3 に答える
設定
ここにあるリンクの一部は少し古く、NetBeans 6.0 を対象としているため、以下は NetBeans 6.8を使用して Java デスクトップ アプリケーションのメモリ リークをプラグインするための小さな更新です。
まず、アプリケーションを広範囲に検索して、メモリ リークの可能性がある一般的な領域/機能を見つける必要があります。次のように選択して、NetBeans プロファイラーを起動します。
プロフィール -> プロフィール Project(プロジェクト名)
次に、次のようにプロファイラーをセットアップします。
ワイド検索
そのため、いつメモリ リークが発生したかを確認し、検索のガイドとして、テレメトリの概要を表示できます (下の図で A としてマークされています)。
ワイド検索を行うときは、アプリケーションが何かを実行してから元の「クリーン」な状態に戻る一連のステップを実行し続ける必要があります。私の場合、いくつかのデータをアプリケーションに挿入し (file->open)、それを表示 (show) してから、すべてクリア (file->new) しました。file->new を実行した後、使用されたヒープと生き残った世代の数が開始時と同じになることを期待していました...ガベージコレクターの実行後もそれらがまだ高い場合は、少しメモリがリークしています。
検索の絞り込み
アプリケーションでメモリ リークを起こす機能を見つけたので、検索を絞り込んで、まだ参照されているオブジェクトを正確に把握します。これは、NetBeans プロファイラーで「ヒープダンプ」を取得することによって行われます。
プロファイル -> ヒープ ダンプを取る...
これにより、概要ページにヒープが表示され、クラス ビューに切り替わり、ルート パッケージ名 (org.yourproject) を入力してプロジェクト クラスをフィルター処理し、インスタンス [%] で並べ替えます。ほとんどのメモリ:
ここで、ワイド検索中にリークが見つかったラウンド トリップ ステップを実行し、別のヒープ ダンプを取得します。
プロファイル -> ヒープ ダンプを取る...
2 つのリストを比較して、最初のダンプよりも 2 番目のダンプの方が多くのインスタンスを持つクラスを探します。より多くのインスタンスを持つクラスは、メモリ リークを起こしている可能性があります。2 番目のダンプ ファイルで、リークしている可能性のあるクラスをダブルクリックして、インスタンス ビューに表示します。
左下には、ダブルクリックした特定のクラスのすべてのインスタンスが表示されます。いずれかを選択すると、そのフィールドと参照が右側に表示されます。このオブジェクトがリークしている可能性があるため、何かがまだオブジェクトへの参照を保持しているに違いありません。参照リストの「this」を右クリックし、「Show Nearest GC Root」を選択します。「No GC root found」というダイアログが返された場合は、Java 仮想マシンが次回ガベージ コレクションを行い、オブジェクトがメモリ リークの原因ではないことを意味します。ただし、ツリーが拡大する場合、これがリークの原因の 1 つになる可能性があります。
このステップの鍵は、リストの一番上から順に作業することです。上の画像では、IntDataValue がリークしていると思われるオブジェクトであり、ツリー内で次に下にあるのは、それを参照しているオブジェクトです。Field は参照を保持している変数であり、type はそれを保持しているオブジェクトの型です。リストを下に向かって作業するときは、ソースコードにフリックし続け、次のことを自問してください。
これが参照を保持しているのはなぜですか?
参照を保持する必要がありますか?
ツリーをたどりながら、これらの質問を自問自答しているときに、デバッガーを実行してコードをステップ実行することが、答えを見つける唯一の方法であることがよくあります。
更新: 検索の絞り込みを支援
上記は、検索を絞り込むために使用していた元のメカニズムですが、[プロファイル] メニューの [メモリ スナップショットの比較...] 機能を使用して、検索を絞り込む別の方法を見つけました。最初にスナップショットを作成します (スクリーンショットを参照)。
ここで、ワイド検索中にリークが見つかった往復ステップを実行し、別のスナップショットを作成します。[名前を付けて保存...] ボタンを使用して、見つけやすい場所に保存します。
[プロファイル] -> [メモリ スナップショットの比較...] を選択します。
最初のスナップショットを一番上のスロットに、2 番目のスナップショットを一番下のスロットに入れるように注意しながら、2 つのスナップショットを選択します (そうしないと、誤った負のメモリ変更が発生します)。
これにより、次のような画面が生成されます。ここで、バイト数は 2 つのスナップショット間の割り当ての変更のサイズです (つまり、大きな増加は、割り当て数の変更に伴うメモリ リークの疑いがある可能性があります)。
ウェブ上には、あなたを助けることができるいくつかのリソースがあります
http://www.javapassion.com/handsonlabs/nbprofilermemory/
http://www.netbeans.org/kb/articles/nb-profiler-uncoveringleaks_pt1.html
http://kirk.blog-city.com/more_on_memory_leaks.htm
簡単に言えば、アプリケーションによってメモリに保持されているオブジェクトである「生き残ったジェネレータ」を監視します。
このメトリクスが手に負えなくなったことがわかったら、Memory Live プロファイリング モードに切り替えて、生き残ったジェネレーターでクラスを並べ替え、マウスの右クリック ボタンで [Show Allocation Stack Traces] オプションを選択します。
NetBeans プロファイラーのすべてのドキュメントは、NetBeans Web サイトにあります。紹介から高度な使用まで、プロファイラー専用のセクション全体があります。