ヒープダンプの解析
HeapAnalyzerを使うと、ヒープ内にあるオブジェクトをクラス名で検索することができます。例えば、WASのHttpSessionの実体は「MemorySessionData」というクラスです。このクラスをヒープダンプから検索します。検索クラス名は正規表現で入力します。
検索結果が表示されます。このデータでは、セッションのサイズが1,792bytesであることが分かります。
| 列タイトル(左から) | 意味 |
| TotalSize | 各オブジェクトのサイズです。このオブジェクトが子(属性、クラス変数)を持つ場合は、その子のサイズを含めた合計のサイズとなります。 |
| Size | 子オブジェクトを含めない、オブジェクトそのもののサイズです。 |
| No.Child | 子オブジェクトの数です。 |
| Address | 参照アドレスです。同じクラスでも、別のインスタンスであればアドレスが異なります。 |
| Object | クラス名が表示されます。先頭に「class」と表示される場合は、クラス定義のサイズとなります。クラス定義には、static宣言されたクラス変数のサイズが含まれます。 |
では、このオブジェクトがどのような参照を持つかを調べてみましょう。
![テーブルから調べたいオブジェクトを選択→[Find object in tree view] テーブルから調べたいオブジェクトを選択→[Find object in tree view]](http://cz-cdn.shoeisha.jp/static/images/article/1633/Image4.gif)
ツリービューが開きます。この画面でオブジェクトの親子階層、それぞれのサイズを詳しく調べることができます。MemorySessionDataは、SessionSimpleHashMapの中にあることが分かります。
メモリリークの検出
HeapAnalyzerはメモリリークの検出にも役立ちます。[Analysis]-[Search Name]で、調査したいクラスのパッケージ名の一部を正規表現で入力します。
.*jp/co/XXX.*
パッケージ名で絞り込まれたオブジェクトの一覧が表示されます。この一覧からメモリリークを以下の方法で探索します。
- サイズの大きなオブジェクトのツリーを調べる。
- 起動時の一覧と、メモリリークを起こした状態での一覧を比較する。
- 一覧の中で想定以上の数がインスタンスが生成されているオブジェクトを見つける。
サイズや数が増加していればメモリリークの可能性があるので、ツリーを詳しく調査すれば、メモリリークを起こしたオブジェクトを特定できます。
セッションオブジェクトにコレクションを使う際は要注意!
例えば、セッション内にユーザー情報を保持します。このようなとき、ユーザー情報をコレクションクラスに保持し、それを更にセッション内に保持するようなことは避けましょう。
public class UserInfoBean { private Hashtable table; public String getUserName(){ return table.get("username"); } }
public class UserInfoBean { private String userName; public String getUserName() { return username; } }
JavaBeanの形(POJO)ならば、サイズが必要最小限に抑えられます。
コレクションクラスは、保持すべき情報そのもの以外にハッシュ領域を持つため、不必要にサイズが大きくなります。コレクションクラスを使う必然性がないのであれば、できるだけPOJOを使いましょう。
最後に
以上、オブジェクトのサイズを計測する方法を説明しました。今までは感覚的に「大きい」「小さい」と言っていたサイズが正確に計測でき、問題点の解析、チューニングがやりやすくなります。また、メモリリークを簡単に観測できるようになります。
これまで手探りでメモリリークを探していた方、ぜひお試しあれ!
参考資料
- 手動によるヒープ・ダンプの生成
- 単純なメモリー・リーク検出の開始

![[Analysis]-[Search Name]→「.*MemorySessionData.*」と入力→[Find] [Analysis]-[Search Name]→「.*MemorySessionData.*」と入力→[Find]](http://cz-cdn.shoeisha.jp/static/images/article/1633/Image3_s.gif)
