まめーじぇんと@Tech

技術ネタに関して (Android, GAE, Angular). Twitter: @mame01122

メモリリークの確認方法

今回は、以前から気になっていたAndroidでのメモリリークに関して。
Bitmapを扱う部分など、ドキドキしていたので、今回しっかりとメモリダンプの取得方法を勉強してみました。

今回は、DDMSを使って取得しています。
やり方は、下記の通りです。

  • まず、DDMSを立ち上げ、Devicesのタブからヒープメモリを取得したいアプリ(パッケージ名)を選択します。
  • 選択した状態で、そのすぐ上にある"Update Heap"のアイコンを押します。これで、ヒープメモリの取得が始まります。
  • トラックしたいアプリを立ち上げ、操作します(ここは確認したいシナリオに応じて操作が異なりますね)
  • 終了したら、アプリを抜けます。僕は何となくBackキーで抜けるように(ちゃんとonDestroyが走るように)しています。
  • DDMSに戻り、"Heap"のタブを選択、"Cause GC"のボタンを押し、ガベージコレクションを走らせます(この段階でGCで解放されなかったメモリが、メモリリークとなります)
  • 続いて、"Devices"のタブに戻り、"Dump HPROF File"のボタンを押します。こうすると、ヒープメモリの情報がHPROF形式で出力されます。
  • hprof-convコマンドを使って、標準のhpof形式のファイルを作成します。hprof-convコマンドは、Android SDKの中にあります。(僕の場合は、tools以下にありました)コマンドは、
hprof-conv xxx.xxx.xxx.hprof(xxx.xxx.xxx.hprofは先ほど出力されたもの) yy.hprof

です。

  • 続いて、jhatコマンドで、その内容を表示します。
jhat yy.hprof

とやると、内部でローカルサーバが立ち上がります。

  • http://localhost:7000/にアクセスすると、ヒープの内容が確認できます。
  • ここから、確認したいアプリのパッケージ名を探します(クラスごとに表示されるので、大量に表示されるかと思います)
  • 該当するクラスを選択して別ページに遷移後、"Reference to this object"の項目にリンクがあるものが、メモリリークです。これをやっつけましょう。
  • どこから参照されているためにリークしているかを確認するためには、"excludes weak refs"のリンクをクリックし、次のページに遷移します。
  • ここで、Static referenc from "xxx.xxx.xxx.(クラス名)”となっているものが原因です。ここを修正しましょう。

とりあえずこんな感じ。

他のアプリもついでに確認しましたが、結構バイト単位ではリークしていたりで、
一昔前の組み込みでもないので、そこまで厳密にやらなくてもいいかも・・・という気はしますが、
知っておいて損はないものだと思うので、備忘録の意味もかねて書きました。

何か違うよー、などありましたらご指摘くださいませ。
※本当はスクリーンショットをつけた方がわかりやすいんでしょうが、何せ面倒で。。。