Upload
baroqueworksdev
View
992
Download
1
Embed Size (px)
Citation preview
LeakCanaryでメモリリーク調査
@nory_kaname
自己紹介
● 組み込みエンジニア
● 携帯電話開発 (9年 )o ガラケーo スマートフォン
● Android Developer(5年 )o 組み込み支援o Frameworkカスタマイズo アプリケーション開発
● クックビズ株式会社所属
執筆
プロの力が身につく Androidプログラミングの教科書
本編
● LeakCanaryを使おうo Leak検知時に Notification通知してくれる
● Android標準のメモリリークも存在する● 困った時は、 stackoverflowで聞け● Githubにコントリビュートよろしく
絶対に LeakCanaryをいれろ!!
まとめ
なんでカナリア
● 毒ガス検知o いわゆる炭鉱のカナリアは、炭鉱においてしばしば発生するメタンや一酸化炭素といった窒息ガスや毒ガス早期発見のための警報として使用された。本種はつねにさえずっているので、異常発生に先駆けまずは鳴き声が止む。つまり危険の察知を目と耳で確認できる所が重宝され、毒ガス検知に用いられた。
引用元: http://ja.wikipedia.org/wiki/カナリア
メモリリークを埋め込むやつら
● いまだに「 Javaはメモリリークしない」と信じてるプログラマ
● ライフサイクルを理解していない● APIリファレンスを読まない● 死んでほしいレベルの設計
close(),unregist(),recycle()など終了処理をしていない、なんでもかんでも thisを渡す。
LeakCanaryとは
● Square社のライブラリo https://github.com/square/leakcanaryo メモリリーク検知ライブラリ
メモリリーク検知!!
Activity.onDestory時にメモリリークチェックリーク検知すると、 Notificationに通知参照オブジェクトをリスト表示
処理はこんな感じ
● Applicationクラスを LeakCanaryに渡す(LeakCanary.java)
● ActivityLifecycleCallbacksを利用して Activity.onDestroyをフック (ActivityRefWatcher.java)
● WeakReference で参照チェック (RefWatcher.java)o Backgroundスレッド (Executor)でチェック実行o GC実行、 hprofファイル取得
AndroidHeapDumper.java Debug.dumpHprofData()使用
導入が楽々!!
Step.1 ライブラリ追加build.gradleに記載
dependencies {debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
}
導入が楽々!!
Step.2 Applicationクラスから callする
public class ExampleApplication extends Application {
@Override public void onCreate() {super.onCreate();LeakCanary.install(this);}
}
Fragmentのリークチェック
LeakCanary.install()時に RefWatcherを取得
public class ExampleApplication extends Application {private RefWatcher refWatcher;
public static RefWatcher getRefWatcher(Context context) { ExampleApplication application = (ExampleApplication)context.getApplicationContext(); return application.refWatcher;}
@Override public void onCreate() {super.onCreate();refWatcher = LeakCanary.install(this);
}}
Fragmentのリークチェック
Fragment.onDestroy()で watchを call
public abstract class BaseFragment extends Fragment {
@Override public void onDestroy() {super.onDestroy();RefWatcher refWatcher =
ExampleApplication.getRefWatcher(getActivity());refWatcher.watch(this);
}}
リークを検知すると
Notificationで通知してくれる
リークを検知すると
Activity起動、参照オブジェクトをリスト表示
Logcatに出力してくれる
logcatでの出力05-10 18:13:00.377 9098-9965/com.ponnex.justdrive D/LeakCanary In com.ponnex.justdrive:1.0:1.﹕* com.ponnex.justdrive.DebuggingActivity has leaked:* GC ROOT static android.support.v4.content.LocalBroadcastManager.mInstance* references android.support.v4.content.LocalBroadcastManager.mReceivers* references java.util.HashMap.table* references array java.util.HashMap$HashMapEntry[].[51]* references java.util.HashMap$HashMapEntry.key* references com.ponnex.justdrive.DebuggingActivity$3.this$0 (anonymous class extends android.content.BroadcastReceiver)* leaks com.ponnex.justdrive.DebuggingActivity instance* Reference Key: 4fea07d9-9369-4618-a8e0-9e63b3e1b908* Device: samsung samsung GT-I9100 pa_i9100* Android Version: 5.1.1 API: 22* Durations: watch=5219ms, gc=244ms, heap dump=4978ms, analysis=19968ms
リーク出典: http://stackoverflow.com/questions/30150272/memory-leak-on-appcompatactivity-using-leakcanary
Android標準のリークもあるよ
logcatでの出力 * LEAK CAN BE IGNORED. * jp.co.XXXXXXXXXXXXX has leaked: * GC ROOT android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper.mParentInputMethodManager * references android.view.inputmethod.InputMethodManager.mCurRootView * references com.android.internal.policy.impl.PhoneWindow$DecorView.mContext * leaks jp.co.XXXXXXXXXXXXX has leaked instance * Reference Key: 2807fc51-f9b4-4a1f-b6ba-33ba244189ec * Device: LGE google Nexus 5 hammerhead * Android Version: 5.1 API: 22 * Durations: watch=5062ms, gc=156ms, heap dump=1639ms, analysis=15535ms
IGNOREDと出力されます
Android標準のリークもあるよ
すでに確認されているリークは、 AndroidExculedRefs.javaに記載https://github.com/square/leakcanary/blob/master/leakcanary-android/src/main/java/com/squareup/leakcanary/AndroidExcludedRefs.java
Android標準のリークを発見した
発見した場合、以下の手順で issueに登録● leak trace情報を登録● AOSPのソースを確認、何が起こったか調査。
https://github.com/android/platform_frameworks_base● Fix済みかどうか、最新 Android Verで確認。再現手順確立
● AOSPの issue trackerに登録https://code.google.com/p/android/issues/list
● AndroidExcludedRefs.javaを修正して、 LeakCanaryに pull request
ここに登録: https://github.com/square/leakcanary/issues
リーク調査で困ったら
困ったら stackoverflowで聞け!! (公式 )
私も回答します。
聞くだけじゃなくて、回答する側になろう
ご静聴、ありがとうございました。