プロファイル結果 - メモリー使用
メモリー使用を解析すると、「プロファイル結果」タブに、オブジェクトの割り当てとライブに関するデータが表示されます。これらの結果は、次のプロファイルタスクを選択すると表示されます。
メモリー使用を解析する場合、表示されるプロファイル結果は次のどのオプションを選択したかによって異なります。
- オブジェクト作成とガベージコレクションの両方を記録 (オブジェクトライブ)
このオプションを指定すると、まだ実行中であるオブジェクトの数がオブジェクトの種類ごとに表示されます。また、ライブオブジェクトに関するデータも表示されます。
- オブジェクト作成のみ記録 (オブジェクト割り当て)
このオプションを指定すると、割り当て済みのオブジェクトの数、種類、位置に関する情報を取得できます。このプロファイルモードは、オブジェクトライブのプロファイルの機能的なサブセットです。モードが 2 つあるのは、オブジェクト割り当てのみをプロファイルするとパフォーマンスとメモリーオーバーヘッドが軽くなるためです。
「プロファイル結果」タブを開くには、「Profiler」ウィンドウで「ライブ結果」ボタン (
) をクリックします。
メモリー使用の解析結果
オブジェクトライブをプロファイルすると、「プロファイル結果」タブに次の情報が表示されます。(オブジェクトライブのプロファイル結果の例については、ここをクリックしてください。)
- 「ライブバイト数」 (グラフ)
- 「ライブバイト数」 (数)
- 「ライブオブジェクト数」
この値は、特定のクラスで追跡されるライブオブジェクトのこの時点のサイズと個数です。追跡されるオブジェクトは、スタックトレースが収集され、サイズが特定され、ライブ状態が監視されるすべての割り当てオブジェクトのサブセットです。この統計データ収集方法の詳細を参照してください。オブジェクト割り当てのプロファイルの場合と同様に、時間的なオーバーヘッドと空間的なオーバーヘッドの両方を引き続き制御するために、オブジェクトのごく一部だけ (たとえば、10 分の 1 または 20 分の 1) を追跡することを推奨します。追跡するオブジェクトの割合は、「メモリー使用を解析」コマンドダイアログで、またはカスタムメモリープロファイルを実行する場合に変更できます。
- 割り当てオブジェクト数
この値は、割り当て済みの追跡されるオブジェクトの総数です。
- 平均年齢
この値は、このクラスで追跡されたライブオブジェクトの平均年齢です。オブジェクトの年齢は、オブジェクトが生存してきたガベージコレクション (GC) の回数が測定されます。世代ガベージコレクタ (HotSpot JVM のデフォルト) が使用されている場合、Profiler では現在、部分的なガベージコレクション (Young 世代) と、完全なガベージコレクションが区別されていません。平均年齢は、すべてのオブジェクトの年齢の合計をオブジェクトの数で割った値です。
- 世代数
特定のクラスのオブジェクトに対するこの測定値は、複雑な方法で計算されます。本質的には、この値は、このクラスのオブジェクトについての異なるオブジェクトの年齢の総計を表します。あるクラスについてこの数が絶えず増加している場合は、通常、メモリーリークの兆候を示しています。それは、メモリーリークとは (少なくとも、もっとも危険な種類のメモリーリークの場合は)、あるクラスのオブジェクトが常に割り当てられているが、部分的にしか回収されない状況であるためです。リーククラスの逆呼び出しグラフを取得することにより、どの割り当て位置に世代数の最大値があるか、つまり、どの割り当て位置がほとんどまたはすべてのリークオブジェクトを生成しているかを判定できます。オブジェクトがどこに割り当てられているかがわかると、一般には、メモリーリークの原因を特定することが容易になります。
- 合計割り当てオブジェクト数
このクラスの割り当てオブジェクトの総数。この数は、オブジェクト割り当てのプロファイルを実行したときに取得される数と同じであり、割り当てられている特定のクラスのオブジェクトの実際の総数を表します。
各列ヘッダーをクリックするか、またはローカルのポップアップメニューを使用することにより、上に示した任意の数でクラスをソートできます。また、特定のクラスのプロファイルを停止することも選択できます。
特定のクラスのプロファイルを停止する
オブジェクトライブをプロファイルするときは、プロファイルするクラスを制限できます。クラスを右クリックすると、選択されたクラスまたは選択されたクラスの下に表示されたすべてのクラスのプロファイルを停止するオプションを含むコンテキストメニューを開くことができます。このオプションは、多数のクラスを含むアプリケーションをプロファイルしており、目的のクラス (たとえば、もっとも生存時間の長いクラスやリーククラス) がすでにわかっている場合に役立ちます。この状況では、一般に、その他のすべてのクラスのプロファイルを停止することにより、不必要なランタイムオーバーヘッド (これは非常に大きくなる場合がある) を回避することが有効です。
Profiler によるオブジェクトライブの追跡方法
Profiler は、以前に割り当てを登録したオブジェクトのみのライブ状態を追跡します。つまり、ほかの一部のツールとは異なり、ヒープのスナップショットは作成しません。代わりに、Java WeakReferences を、割り当て済みとして登録したオブジェクトと内部的に関連付けます。プログラムの実行中にオブジェクトライブのプロファイルを開始するか、またはプロファイルがアクティブな間に「プロファイル」>「収集結果をリセット」
を起動した場合は、ターゲット VM のヒープ上にあるすべてのライブオブジェクトが表示されない可能性があります。ただし、時間の経過とともに割り当てオブジェクトが多くなりすぎる問題やメモリーリークといった、オブジェクトライブのプロファイルが対応しているもっとも重要な問題の解決にとって、これは大きな支障にはなりません。こうした状況では、かなり前 (場合によっては、アプリケーションの起動時) に割り当てられたオブジェクト数より、現在アプリケーションに割り当てられ、ガベージコレクトされているオブジェクト数を調べることの方が重要になります。
オブジェクト割り当ての結果
オブジェクト割り当てをプロファイルすると、「プロファイル結果」タブに、クラス (配列クラスを含む) の一覧が、計測コマンド発行後に割り当てられたインスタンスの合計サイズと個数とともに表示されます。(オブジェクト割り当てのプロファイル結果の例については、ここをクリックしてください。)
オブジェクト割り当てのプロファイルを有効にすると、ターゲット JVM で現在読み込まれているすべてのクラス (および新規に読み込まれる各クラス) が計測され、オブジェクト割り当てに関する情報が生成されます。Profiler によって表示されるオブジェクト割り当ての数は正確です。これに対して、合計のオブジェクトサイズと逆呼び出しグラフはどちらも、デフォルトでは統計的に取得されます。Profiler でこの処理がどのように実行されるかの詳細については、「メモリープロファイルでの半統計的データ収集」を参照してください。
結果の使用: リークアプリケーション
下の図に、リークしているクラス String のインスタンスを最初に特定するリークアプリケーションの例を示します。これは、オブジェクト自体の数が比較的少ないにもかかわらず、このクラスの生存中世代の数がほかの種類よりはるかに多く、しかもその数が絶えず増加しているためです。
次に、「正常な」String インスタンスではなく、リークしている String インスタンスが割り当てられているコード内の場所を特定します。(この場所でも、生存中世代の数がほかよりはるかに多くなっている。)
関連項目