23
LeakCanary で でででででででで @nory_kaname

Leak canaryで メモリリーク調査

Embed Size (px)

Citation preview

Page 1: Leak canaryで メモリリーク調査

LeakCanaryでメモリリーク調査

@nory_kaname

Page 2: Leak canaryで メモリリーク調査

自己紹介

● 組み込みエンジニア

● 携帯電話開発 (9年 )o ガラケーo スマートフォン

● Android Developer(5年 )o 組み込み支援o Frameworkカスタマイズo アプリケーション開発

● クックビズ株式会社所属

Page 3: Leak canaryで メモリリーク調査

執筆

プロの力が身につく Androidプログラミングの教科書

Page 4: Leak canaryで メモリリーク調査

本編

Page 5: Leak canaryで メモリリーク調査

● LeakCanaryを使おうo Leak検知時に Notification通知してくれる

● Android標準のメモリリークも存在する● 困った時は、 stackoverflowで聞け● Githubにコントリビュートよろしく

絶対に LeakCanaryをいれろ!!

まとめ

Page 6: Leak canaryで メモリリーク調査

なんでカナリア

● 毒ガス検知o いわゆる炭鉱のカナリアは、炭鉱においてしばしば発生するメタンや一酸化炭素といった窒息ガスや毒ガス早期発見のための警報として使用された。本種はつねにさえずっているので、異常発生に先駆けまずは鳴き声が止む。つまり危険の察知を目と耳で確認できる所が重宝され、毒ガス検知に用いられた。

引用元: http://ja.wikipedia.org/wiki/カナリア

Page 7: Leak canaryで メモリリーク調査

メモリリークを埋め込むやつら

● いまだに「 Javaはメモリリークしない」と信じてるプログラマ

● ライフサイクルを理解していない● APIリファレンスを読まない● 死んでほしいレベルの設計

close(),unregist(),recycle()など終了処理をしていない、なんでもかんでも thisを渡す。

Page 8: Leak canaryで メモリリーク調査

LeakCanaryとは

● Square社のライブラリo https://github.com/square/leakcanaryo メモリリーク検知ライブラリ

Page 9: Leak canaryで メモリリーク調査

メモリリーク検知!!

Activity.onDestory時にメモリリークチェックリーク検知すると、 Notificationに通知参照オブジェクトをリスト表示

Page 10: Leak canaryで メモリリーク調査

処理はこんな感じ

● Applicationクラスを LeakCanaryに渡す(LeakCanary.java)

● ActivityLifecycleCallbacksを利用して Activity.onDestroyをフック (ActivityRefWatcher.java)

● WeakReference で参照チェック (RefWatcher.java)o Backgroundスレッド (Executor)でチェック実行o GC実行、 hprofファイル取得

AndroidHeapDumper.java Debug.dumpHprofData()使用

Page 11: Leak canaryで メモリリーク調査

導入が楽々!!

Step.1 ライブラリ追加build.gradleに記載

dependencies {debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'

}

Page 12: Leak canaryで メモリリーク調査

導入が楽々!!

Step.2 Applicationクラスから callする

public class ExampleApplication extends Application {

@Override public void onCreate() {super.onCreate();LeakCanary.install(this);}

}

Page 13: Leak canaryで メモリリーク調査

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);

}}

Page 14: Leak canaryで メモリリーク調査

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);

}}

Page 15: Leak canaryで メモリリーク調査

リークを検知すると

Notificationで通知してくれる

Page 16: Leak canaryで メモリリーク調査

リークを検知すると

Activity起動、参照オブジェクトをリスト表示

Page 17: Leak canaryで メモリリーク調査

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

Page 18: Leak canaryで メモリリーク調査

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と出力されます

Page 19: Leak canaryで メモリリーク調査

Android標準のリークもあるよ

すでに確認されているリークは、 AndroidExculedRefs.javaに記載https://github.com/square/leakcanary/blob/master/leakcanary-android/src/main/java/com/squareup/leakcanary/AndroidExcludedRefs.java

Page 20: Leak canaryで メモリリーク調査

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

Page 21: Leak canaryで メモリリーク調査

リーク調査で困ったら

困ったら stackoverflowで聞け!! (公式 )

Page 22: Leak canaryで メモリリーク調査

私も回答します。

聞くだけじゃなくて、回答する側になろう

Page 23: Leak canaryで メモリリーク調査

ご静聴、ありがとうございました。