演習 1.3: リーク候補の分析
始める前に、『演習 1.2: ヒープ・ダンプの取得』を完了する必要があります。
この演習では、リークすると思われるオブジェクト (配列、ベクトル、およびセッションなど) のリストを最初に生成します。これらが「リーク候補」です。次にリストを分析してリークを識別します。
リーク候補のリストの生成
リストを生成するには以下を行います。
- 「リーク候補」ビューの指示に従い、「リークの分析」ツールバー・ボタン
をクリックします。「リーク分析オプションの選択」ダイアログ・ボックスが開きます。
- ダイアログ・ボックスで、ご使用の 2 つのヒープ・ダンプのチェック・ボックスにチェックが入っていることを確認します。
注: デフォルトのしきい値は 20 です。これは、リーク候補のうち、可能性の値が 20 以上のものだけが表示されることを意味します。(可能性の値については、この演習の後半で詳しく説明します。)
- 「OK」をクリックしてリストを生成します。Software Development Platform 左下隅のインディケーターに、リーク候補を検出中であることがレポートされます。
「リーク候補」ビューの概要
プロセスが終了すると、「リーク候補」ビューにリーク候補のリストが表示されます。
それぞれの候補は 100 から 1 までの間の可能性の値を持ち、最も可能性の高い候補が 100 の値を持ちます。他の候補はそれぞれの可能性に応じてランクされ、可能性が降順になるようにリストされます。
(ヒープ比較アルゴリズムは、リークのサイズと、2 つのヒープ・ダンプの時間間隔での増加を基にして、可能性の値を計算します。
このプロファイルの実行では、しきい値が 20 に設定されていたため、可能性の値が 19 以下の候補は表示されません。
ビューはそれぞれのリーク候補について、以下のデータを提供します。
- リーク・ルート。これは、リークの可能性があるオブジェクトへの参照を保持する、最上位のルート・オブジェクトです。
- コンテナー・タイプ。これは、リークしたオブジェクトを保持する収集オブジェクトです。リークが最も発生しやすいのは、ベクトルやリストなどの収集オブジェクトです。
- リーク内容。これはリークしたオブジェクトのタイプです。
- リークの数。この値はコンテナー・オブジェクト内にある、「リーク内容」列で指定されたタイプのオブジェクトの数を示します。これらのオブジェクトは別のオブジェクトを参照していることもあります。「リークしたオブジェクト」および「リークしたバイト数」列は、これらの参照されたオブジェクトも含みます。
- リークしたバイト数。
- リークしたオブジェクト。
リークの分析および識別
リークを識別するには以下を行います。
- 「リーク候補」ビューで、可能性が 100 のリーク候補に関するデータを見ます。
- リークのルートは TestThreeTierQueue.<ObjectID> です。
- コンテナー・タイプは vector です。
- ベクトルは文字列をリークしています。言い換えると、ベクトルは文字列への参照を保持していますが、リークの数とリークしたバイト数から判断すると、文字列への参照を解放して、ガーベッジ・コレクションがメモリーをフリーにできるようにする必要があります。(リークの数とリークしたバイト数は、ヒープ・ダンプの取得タイミングに応じてプログラムを実行するたびに異なる可能性があります。)
- リーク候補をダブルクリックします。「オブジェクト・リファレンス・グラフ」ビューが開いて、リーク候補に関するデータをグラフィック表示します。(ヒープ・ダンプの表示の準備に、しばらく時間がかかることがあります。)
- オブジェクト・リファレンス・グラフを調査します。次の点に注意してください。
- グラフでは、参照によって可能性のあるリークへ接続されているオブジェクトが強調表示されます。つまり、リークのルートから SecondaryQueue を介して、ベクトルを経て、最終的にはリークした文字列セットに至ります。これにより、リーク内容についてのビジュアルなイメージが提供されます。
- グラフには、Vector に参照される Object 配列 (リークに関与するコンテナー・タイプ) と、リークする String オブジェクトを参照する Object 配列があります。
- Object 配列と String を接続するパスの上にカーソルを停止させ、表示されるツールの説明を読みます。「カウント」が「リーク候補」ビューに表示されているリーク数に等しいことが表示されますが、これがリークとして識別された文字列のコレクションです。
- 2 次キューおよび 3 次キューの両方が Object 配列への参照を保持していますが、3 次キューは「リーク候補」ビューではリークとして識別されません。これについては、いくつかの説明が考えられます。
- 3 次キューは実際リークしているが、2 次キューよりも速度が遅い。しきい値をデフォルト値の 20 より低くしてリーク分析を再度実行すると、3 次キューについてもリークが表示される場合があります。
- 3 次キューが Object 配列オブジェクトへの参照を保持する正当な理由があるため、メモリーはリークしているのではなく保存されている。2 次キューのコードを修正して改良したアプリケーションを再実行すれば、その答えが確認できます。
- オブジェクト・リファレンス・グラフで String オブジェクトをダブルクリックします。「オブジェクト詳細」ビューが開きます。String オブジェクトについて、それを参照するすべてのオブジェクトと、逆にそれが参照するすべてのオブジェクト含む、詳細のすべてが表示されます。「オブジェクト詳細」ビューでは、参照元の 1 つをクリックして参照元を上へナビゲートしたり、参照先 (そのオブジェクトが参照するオブジェクト) の 1 つをクリックして参照先を下へナビゲートしたりできます。
何を検出しましたか。2 次キューがリークしているオブジェクトで、Vector オブジェクトが多くの String オブジェクトへの参照を保存していることがリークの原因だということが分かりました。
『演習 1.4: メモリー・リークの修正』に進んでください。