ご挨拶
この記事はピクシブ株式会社 AdventCalendar 2017 21日目の記事です。
今年の5月に中途入社した@verno3632と申します。前職ではインフラエンジニアをやりながら、趣味でAndroidアプリを書いていました。非公式アプリを続けていたらいつのまにか入社していました。
現在ではpixivコミックというサービスのチームでAndroidアプリを作っています。KotlinとかDaggerとかArchitecture Componentsとか興味あるものからとりあえず入れてみてます。
今回はLeakCanaryの話です。
LeakCanary
言わずと知れたSquareのライブラリで、入れておくとアプリ実行時にメモリリークを検知して通知してくれます。入れてて当然ですよね?
Logcatを見るまでもなく、Android上だけでどこから何が漏れているのかわかるので非常にありがたい。
ですがシンプルな画面なため詳しい調査には情報が足りないよということがあります。
わかんないよ。
クラス名がリーク元・先として表示されるので、そのクラスを元にあたりをつけていくわけですが、自分で書いたわけではないコードのクラスだったりすると検討がつきません。
ということで調べてみましょう。
Heap Dumpを取得する
メモリの調査をするならまずHeap Dumpです。
最近のAndroidStudioではAndroid Profilerのおかげで簡単にDumpを取ることができるようになりました。
LeakCanaryではHAHAという、これまたSquareのライブラリを使って、Dumpをとっています。
初回起動時にファイル書き込み権限を求められるのも、リークを起こした際に時が止まるのもDumpをとってファイルに吐いているためですね。
Dumpファイルはhprofなので取り出して他ツールで読むことができます。
ファイルの保存場所は、Logcatに以下のようなログが流れてくるのでそこを参考にします。
hprof: heap dump “/storage/emulated/0/Download/leakcanary-${package}/hogehoge.hprof” starting...
hprof: heap dump completed (12MB) in 3.456s objects 789012 objects with stack traces 0
ディレクトリごとまるっと持ってきた方が早いかもしれません。
adb pull /storage/emulated/0/Download/leakcanary-${package}
DumpファイルをAndroid Studioで読み込む
hprofをAndroid Studioで表示するには、プロジェクト直下のcaptures
ディレクトリにファイルを置きます。
captures
は各種snapshotを置いておくディレクトリで、Layout Inspectorで撮ったキャプチャなどもここに入ってきます。
View > Tool Windows > Captures
を開くと左のWindowからcaptures
以下が見えます。
リーク元を調べる
hprofファイルを選択するとHPROF Viewer/Analyzerが開きます。
まず最初にリークしているインスタンスを探しましょう。
右のWindowのAnalyzer Tasks
を実行するのが早いですが、KeyedWeakReference
のクラスから探すのもありです。KeyedWeakReference
はLeakCanaryが検知したリーク先への参照を持っています。
次にリーク元を探します。
インスタンスを選択すると下のWindowのReference Tree
にそのインスタンスに関する参照が表示されます。
一番下の方にあるreferent
を見ると、どこから参照されているかがわかります。
RefWatcher
はLeakCanaryからの参照なので問題ありません。weakActivity
から漏れていますね。
数値計測用に入れていた3rd partyのSDKからでした。
おわりに
LeakCanaryを使ってメモリリークを撲滅し、Picasso/Glideなどのライブラリで画像を扱うことによりOutOfMemoryは以前より格段に減りました。これからも計測・調査を続けてよりよいアプリを作っていきましょう。
ピクシブ株式会社では、クリエイターに向けてサービスを作っていきたいアプリエンジニアを募集しています!
明日は @yensaki です。お楽しみに!