JRockit SDK ユーザーズ ガイド
![]() |
![]() |
![]() |
![]() |
BEA JRockit Memory Leak Detector は、BEA JRockit 上で実行される Java アプリケーション内のメモリ リークを検出するツールです。 メモリ リークとは、実際にはそのアプリケーションでこれ以上使用されないメモリをアプリケーション コードが保持し続けていることを表します。 BEA JRockit Memory Leak Detector は、割り当てられたオブジェクトの種類、回数、サイズ、およびオブジェクト相互の関連性に関する情報を提供するリアルタイムのプロファイリング ツールです。 他の同様のツールとは異なり、後で分析するためにヒープ全体のダンプを作成する必要はありません。 表示されるデータは実行中の JVM から直接取得され、JVM は比較的小さなオーバーヘッドで実行を続けることができます。 分析が行われるときはツールの接続を切断できるため、JVM は再び通常の速度で実行されます。 したがって、このツールはプロダクション環境での実行にも適しています。
このツールの目的は、メモリがリークしているオブジェクトのタイプを表示し、問題の原因を特定しやすくすることです。 もう一つの目的は、理解や知識を深めることにより、開発者が今後のプロジェクトで同様のプログラミング エラーを回避できるようにすることです。
注意 : BEA JRockit Memory Leak Detector の完全なバージョンを利用するには、JRockit JRockit 1.4.2_05 以降が必要です。
この節では、BEA JRockit Memory Leak Detector (以降は Memory Leak Detector という) の起動手順とメモリ リーク検出の手順について説明します。 内容は以下のとおりです。
Memory Leak Detector を起動するには、BEA JRockit Management Console を起動する必要があります (BEA JRockit 1.4.2_05 以降)。
図 5-1 にこのタブの内容を示します。
図 5-1 BEA JRockit Management Console 内の [MemLeak Detector] タブ
各カラムが何を表すかについては、表 5-1 に詳しい説明があります。 メモリ リーク データの収集が始まると、「ManagementServer started trend analysis」というメッセージが JRockit から表示されます。
この節では、Memory Leak Detector の使い方について説明します。 内容は以下のとおりです。
メモリ リーク検出プロセスには次の 3 つの段階があります。
傾向分析では、絶えず更新されるオブジェクト タイプに関する情報を観察して、メモリが不審に増加しているオブジェクト タイプを見つけます。 このようなオブジェクト タイプは、メモリ リーク検出プロセスの次の段階で調査の対象となります。 傾向分析テーブルの情報は、ガベージ コレクションが実行されるたびに更新されます。
オブジェクト タイプの関係の調査では、オブジェクト タイプ (クラスなど) の間の参照パスを繰り返し追跡します。増加を続けるオブジェクト タイプの関係で注目すべきものを探し、その関係に関わるオブジェクト タイプを見つけることが目的です。 メモリが異常に増加しているオブジェクト タイプが見つかったら、メモリ リーク検出プロセスの 3 番目の段階に進みます。
インスタンスの調査では、異常なメモリ サイズのインスタンスや、異常な数の参照があるインスタンスを見つけて、そのインスタンスを調べます。 インスタンスを調べる際には、フィールド名、フィールドの型、フィールド値などの値が表示されます。 これらの値を利用して、アプリケーション コード内で正確なエラーの場所を探します。つまり、その特定のオブジェクト タイプの特定のインスタンスが割り当て、変更、または削除されている場所です (状況の示す内容によって異なります)。 不審なインスタンスに関わる部分にまで問題の場所を絞り込んでゆくと、メモリ リークを起こしている実際の問題をうまく見つけ出して、その問題を修正することができます。
アプリケーションを分析するには、Memory Leak Detector を起動する必要があります (「Memory Leak Detector の起動」を参照)。
以下の節では、メモリ リーク検出プロセスに役立つように Memory Leak Detector を使用する方法について説明します。
メニューが表示されます (図 5-3 を参照)。
[Referring types] ウィンドウが表示されます。その特定のタイプのオブジェクトを指し示すオブジェクト タイプのリストが表示されています (図 5-4 を参照)。
図 5-4 [Referring types] ウィンドウ : 疑わしいオブジェクト タイプの調査
図 5-6 [Largest Arrays] ウィンドウ : 配列インスタンスを大きい順に表示
表示された新しい [Referring instances] ウィンドウ (図 5-7 を参照) では、静的フィールドや、問題のインスタンスを参照しているスレッド ルート数を調べることができます。
図 5-7 [Referring instances] ウィンドウ : 配列インスタンスを指し示すインスタンス
場合によっては、リストが非常に長くなることがあります。その場合は、そのようなリストの表示結果について通知するメッセージが表示されます (図 5-9)。
この節では、検索領域を絞り込んでゆくことでメモリ リークを見つける方法を例を挙げて説明します。 検索領域を絞り込むと、問題の正確な場所をうまく見つけて、アプリケーションを変更することにより問題を解決することができます。
Memory Leak Detector を起動した後、アプリケーションの設計や目的を考えると増加しないはずなのに大きく増加しているオブジェクト タイプを調査の対象として選択します。 この例では、DemoObject オブジェクト タイプ (図 5-10) が該当します。 疑わしいオブジェクト タイプの行を選択して右クリックし、[Show types pointing to this type] メニュー オプションを選択します。
図 5-10 傾向分析から示されたオブジェクト タイプ DemoObject
DemoObject を指し示す 1 つのオブジェクト タイプを示す [Referring types] ウィンドウ (図 5-4) が表示されます。 具体的には HashTable$Entry です。 この疑わしいメモリ リーク パスを追跡するには、該当する行を選択して右クリックし、[Show types pointing to this type] を再びクリックします。
表示された [Referring types] ウィンドウで、前述のオブジェクト タイプを指し示す 2 つのオブジェクト タイプに注目します。 1 つは HashTable$Entry[ ]、もう 1 つは HashTable$Entry です。 HashTable$Entry[ ] タイプからの参照の数が予想よりも大きいことに注目して、この配列型をさらに調べることにします。 この配列型の行を選択して右クリックし、[Show types pointing to this type] を選択します。 新しく表示された [Referring types] ウィンドウでは、オブジェクト タイプ HashTable がこの配列を指し示していることがわかります。
前のウィンドウに戻り、疑わしい配列型を再び選択します。 選択した項目を右クリックしたら、今度は [Show largest arrays of this type] を選択します。 [Largest Arrays] ウィンドウ (図 5-6) が表示されます。この配列のインスタンスが大きい順に 10 個まで表示されています。 この情報から、ある単一の配列インスタンスが大きなメモリ占有率の原因になっていることがわかります。
代わりに他のオプション [Show instances of this type pointing to <TYPE>] (この場合の TYPE は HashTable$Entry) を選択すると、参照の数が多いため JRockit プロセスへの接続が失われるおそれがあるという警告を示した、新しいウィンドウが表示されます。 つまり、HashTable$Entry[ ] は予想以上に多くのメモリを消費しており、HashTable$Entry への多数の参照を保持していることになります。
[Largest Arrays] ウィンドウに戻ります。 疑わしい項目 (メモリを最も多く占有しているインスタンス) を選択します。 [Show instances pointing to this array] を選択します。 [Referring instances] ウィンドウ (図 5-7) が表示されます。その配列を指し示すインスタンスのリストが表示されています。 HashTable インスタンス (図 5-11) です。
[Inspector] ウィンドウ (図 5-8) が表示されます。 このウィンドウでは、さまざまなフィールド名とその型および値を参照できます (図 5-12)。 これらのフィールドや値を、アプリケーション コードの特定の箇所に照らし合わせます。
図 5-12 インスタンスの調査は問題を当該コードに対応付けるのに役立つ
この例からは、どこかで、HashTable によって保持されている HashTable$Entry[ ] に HashTable$Entry インスタンスを追加しているという結論を引き出すことができます。 また、アプリケーションでそのインスタンスを削除していないため、このタイプのオブジェクトが占有しているメモリが増え続けていると考えることができます。 この考えを確認するには、そのインスタンスのフィールド情報が示す場所で、コードを詳しく調べます。
メモリ リークの原因となっている場所をコードの中で確認したところ、HashTable 内で、HashTable$Entry オブジェクトが HashTable$Entry[ ] に追加された後であることがわかりました。 アプリケーションは HashTabe$Entry オブジェクトを 1 つだけ残して全部削除しており、1 つ違い (off-by-one) エラーが原因で最後のインスタンスを見逃していました。このエラーはこの種のメモリ リークの原因としてよく見られるエラーです。
Memory Leak Detector を使用すると、オブジェクト タイプの割り当てに関する統計情報を簡単に入手することができます。 このツールは、開発者がメモリ リークを簡単に見つけ出したり、プログラム エンジニアリングの重要なポイントを理解するのに役立つように設計されています。
このツールの改良方法や開発環境における一般的な使われ方など、上記の目的に沿った提案があればぜひお寄せください。 弊社では、こうした情報をもとに、このツールを今後どのように改良すればよいかを判断することができます。
フィードバックや使い方に関するアイデアは、電子メールで下記の宛先までお送りください。
フィードバックは Memory Leak Detector の設計を担当する開発チームによって検討されます。 集まったアイデアを参考に、BEA JRockit のツールをより使いやすくなるように改良します。 このツールを開発する目的は、メモリ リークを見つけるという難しい作業を簡単にして、開発者が効率的に作業できるようにすることです。
BEA JRockit には扱いやすく好評なツールが既にいくつもありますが、Java Runtime Environment を使用する開発者との緊密な対話を維持できるように、BEA Systems では BEA JRockit の改良方法を絶えず探り続けています。 Memory Leak Detector はその方法の 1 つです。
Memory Leak Detector を完全にサポートしているのは、BEA JRockit の最近のバージョン (BEA JRockit 1.4.2_05) だけです。
Memory Leak Detector に関するよく寄せられる質問は以下のとおりです。
このツールはサポート対象の製品ではないため、提供されるデータの正確性や Memory Leak Detector を使用しているときの製品の安定性に関する保証はありません。
メモリ リーク検出プロセスの最初の段階では、表示データが絶えず更新されますが、この段階でのオーバーヘッドは非常に小さいものです。 2 番目と 3 番目の段階で発生するオーバーヘッドのみがガベージ コレクションに加わりますが、ほとんどの場合は無視してかまいません。 全体として特にオーバーヘッドはなく、アプリケーションの速度や結果には影響を与えません。
Memory Leak Detector は現在、メモリ リークの検出に役立つように参考として現状のままで提供されており、BEA Support によるサポートはありません。
質問がある場合は、BEA JRockit の一般的な問題に関するニュースグループで共有できます。このニュースグループはエンジニアリング チームによってモニタされています。 ニュースグループにアクセスするには、以下に移動してください。
他のインスタンスを参照しているインスタンスを表示するウィンドウに、静的フィールドやスレッド ルート数が正しく表示されない場合があります。 その場合はメモリ リーク検出プロセスを再び開始してください (メモリ リーク システムの連続的な更新を開始してから停止します)。 正しいデータが表示されるようになります。
![]() ![]() |
![]() |
![]() |