実習 1.3: リーク候補の分析
始める前に、実習 1.2: ヒープ・ダンプのキャプチャーを完了する必要があります。
この実習では、リークしていると思われるオブジェクト (配列、ベクトル、セッションなど) のリストをはじめに生成します。これらは「リーク候補」となります。次に、そのリストを分析してリークを識別します。
リーク候補のリストの生成
リストを生成するには
- 「リーク候補 (Leak Candidates)」ビューの指示に従い、「リークの分析 (Analyze for Leaks)」ツールバー・ボタン
をクリックします。「リーク分析オプションの選択 (Select Leak Analysis Options)」ダイアログ・ボックスが開きます。
- ダイアログ・ボックスで、収集した 2 つのヒープ・ダンプのチェック・ボックスにチェック・マークが付いていることを確認します。
注: 「しきい値 (Threshold)」の値は、デフォルトで 20 にセットされています。この設定では、20 以上の「確度 (Likelihood)」の値をもつリーク候補のみが表示されます。(「確度 (Likelihood)」の値についての詳細は、この実習で後ほど説明します。)
- 「OK」をクリックしてリストを生成します。「ソフトウェア開発プラットフォーム (Software Development Platform)」の右下端にあるインディケーターが、リーク候補の検索中であることを知らせます。
「リーク候補 (Leak Candidates)」ビューの概要
処理が完了したら、リーク候補のリストが「リーク候補 (Leak Candidates)」ビューに表示されます。
それぞれの候補は、値が 100 から 1 の間の確度を持ちます。もっとも確実な候補は、値が 100 のものです。他の候補も同様にランク付けされ、確度の降順でリストされます。
(ヒープ比較アルゴリズムは、リークのサイズと 2 回のヒープ・ダンプの間のリークの増加量に基づいて、確度の値を計算します。)
「しきい値 (Threshold)」の値は、今回のプロファイル実行で 20 にセットされているため、「確度 (Likelihood)」の値が 19 以下の候補は表示されません。
それぞれのリーク候補について、次のようなデータがビューで確認できます。
- リークのルート (Root of leak)。これは、リークの可能性があるオブジェクトへの参照を保持しているトップレベルのルート・オブジェクトです。
- コンテナー・タイプ (Container type)。これは、リークしたオブジェクトを保持しているコレクション・オブジェクトです。リークが発生する可能性が最も高いのは、ベクトルやリストのようなコレクション・オブジェクト内です。
- リークのタイプ (What's leaking)。これは、リークしたオブジェクトのタイプです。
- リークの数 (Number of leaks)。この値は、「リークのタイプ (What's leaking)」列で指定されたタイプの、コンテナー・オブジェクト内にあるオブジェクトの数を表します。これらのオブジェクトは、次々に他のオブジェクトを参照している可能性があります。「リークしたオブジェクト (Objects leaked)」列と「リークしたバイト (Bytes leaked)」列は、これらの参照されたオブジェクトを含んでいます。
- リークしたバイト (Bytes leaked)。
- リークしたオブジェクト (Objects leaked)。
リークの分析と識別
リークを識別するには
- 「リーク候補 (Leak Candidates)」ビューで、確度の値 が 100 のリーク候補となるデータに注目します。
- リークのルートは、TestThreeTierQueue.<ObjectID> です。
- コンテナー・タイプは、Vector です。
- この Vector が、リークしているストリングです。すなわち、リークの数とリークしたバイト数から判断して、この Vector がストリングへの参照を保持しており、その参照を解放することで、ガーベッジ・コレクションによってメモリーの空き容量を増やすことができます。(リークの数とリークしたバイト数は、おそらく、このプログラムを実行するたびに違ってきます。これは、ヒープ・ダンプをキャプチャーしたタイミングによるからです。)
- リーク候補をダブルクリックします。「オブジェクト参照グラフ (Object Reference Graph)」ビューが開き、リーク候補についてのグラフィカルなデータが表示されます。(ヒープ・ダンプを表示用に準備するために、いくらか時間がかかることがあります。)
- オブジェクト参照グラフを調べます。次の点に注目してください。
- グラフでは、リークの可能性がある参照によって関連するオブジェクトが強調表示されます。リークのルートから SecondaryQueue を介して Vector へ至り、最後にリークしているストリングのセットへつながっています。これにより、何がリークしているのかを視覚的に捕らえることができます。
- グラフには、Vector (リークに関係するコンテナー・タイプ) によって参照されている Object 配列
があり、Object 配列は、リークしている String オブジェクトを参照しています。
- カーソルを Object 配列と String を接続しているパスの上に置き、表示される
ツールチップをお読みください。「リーク候補 (Leak Candidates)」ビューに表示されたリークの数に等しい「カウント (Count)」が表示されます。これは、リークとして識別されたストリングのコレクションです。
- オブジェクト参照グラフで、String オブジェクトをダブルクリックします。「オブジェクトの詳細 (Object Details)」ビューが開きます。String オブジェクト、それを参照する全オブジェクト、また、それらを次々と参照する全オブジェクトについて、すべての詳細が表示されます。また、「オブジェクトの詳細 (Object Details)」ビューでは、参照元の 1 つをクリックすることで、それを介して上の階層へナビゲートしたり、参照先 (オブジェクトが参照するオブジェクト) の 1 つをクリックすることで、それを介して下の階層へナビゲートすることができます。
結果をまとめてみましょう。「セカンダリー・キュー (Secondary Queue)」が、リークしているオブジェクトであり、それは、
Vector オブジェクトが多くの String オブジェクトへの参照を保持しているためだということが分かりました。
実習 1.4: メモリー・リークの修正を開始する準備が整いました。