leak canary intro jennifer mcgee - meetupfiles.meetup.com/1791179/leakcanaryintro.pdfwrite external...

Post on 06-Jun-2020

5 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

1

Leak Canary Intro

Jennifer McGee

What is Leak Canary?

Leak Canary

•Open source library written by Square’s

Pierre-Yves (PY) Ricau

•Library which attempts to automatically

detect and report memory leaks in android

Leak Cannary

Memory Leaks in Java

3

Objects Reachable

from GC Roots

GC Roots

GC Overview

4

GC Root GC Root

Object

ObjectObject

Object

ObjectObject

Not Reachable from GC Root

GC Roots

GC Overview

5

GC Root GC Root

Object

ObjectObject

Object

ObjectObject

Can be garbage collected

Leak Cannary

How Leak Canary Works

6

Basic Idea

1) Identify objects you are worried about leaking 2) When they are destroyed keep a week reference 3) Wait 4) If not garbage collected notify of possible memory leak

Android Memory Leaks

7

Key Classes

Leak Canary

8

What does RefWatcher Coordinate Leak Canary

9

How Do We Guess when activities Should have been garbage collected?

Android Memory Leaks

10

RecyclerView

11

Q: How can we guess when fragments should have been garbage collected?

A: Extend Fragment

public abstract class BaseFragment extends Fragment {

@Override public void onDestroy() {

super.onDestroy();

RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());

refWatcher.watch(this);

}

}

Leak Cannary

Leak Canary Leak Demo

12

Leak Cannary

13

public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); View button = findViewById(R.id.async_task); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startAsyncTask(); } }); } void startAsyncTask() { // This async task is an anonymous class and therefore has a hidden reference to the outer // class MainActivity. If the activity gets destroyed before the task finishes (e.g. rotation), // the activity instance will leak. new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { // Do some slow work in background SystemClock.sleep(20000); return null; } }.execute(); }}

Activity that Will Leak

Leak Cannary

14

02-21 17:52:58.124 31708-13109/com.example.leakcanary D/LeakCanary: In com.example.leakcanary:1.0:1.

02-21 17:52:58.124 31708-13109/com.example.leakcanary D/LeakCanary: * com.example.leakcanary.MainActivity has leaked:

02-21 17:52:58.124 31708-13109/com.example.leakcanary D/LeakCanary: * GC ROOT thread java.lang.Thread.<Java Local> (named 'AsyncTask #2’)

02-21 17:52:58.124 31708-13109/com.example.leakcanary D/LeakCanary: * references com.example.leakcanary.MainActivity$2.this$0 (anonymous subclass of android.os.AsyncTask)

02-21 17:52:58.124 31708-13109/com.example.leakcanary D/LeakCanary: * leaks com.example.leakcanary.MainActivity instance

02-21 17:52:58.124 31708-13109/com.example.leakcanary D/LeakCanary: * Retaining: 260KB.

02-21 17:52:58.124 31708-13109/com.example.leakcanary D/LeakCanary: * Reference Key: f856c32b-53ad-4f31-bb5b-a51c2208943c

02-21 17:52:58.124 31708-13109/com.example.leakcanary D/LeakCanary: * Device: Genymotion generic Samsung Galaxy S4 - 4.4.4 - API 19 - 1080x1920 vbox86p

02-21 17:52:58.124 31708-13109/com.example.leakcanary D/LeakCanary: * Android Version: 4.4.4 API: 19 LeakCanary: 1.4-SNAPSHOT

What a Leak Log Looks Like

What has Leaked

GC Root

How much Memory

Reference Key

Android Memory Leaks

How to Setup Leak Canary in your App

15

RecyclerView

16

Basic Leak Canary SetupIn your Gradle File:

dependencies {

debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'

releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'

testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'

}

In your Application Class:

public class ExampleApplication extends Application {

@Override public void onCreate() {

super.onCreate();

LeakCanary.install(this);

}

}

Android Memory Leaks

What about Memory Leaks you Can’t Fix?

17

LeakCanary

18

What Does LeakCanary.install(this) do? Lets look at the source

public static RefWatcher install(Application application) {

return install(application, DisplayLeakService.class,

AndroidExcludedRefs.createAppDefaults().build());

}

public static RefWatcher install(Application application,

Class<? extends AbstractAnalysisResultService> listenerServiceClass,

ExcludedRefs excludedRefs) {

Look there it has an

overwritten constructor!

We

pass

in

Excl

uded

Ref

s O

bjec

t

LeakCanary

19

How To Add 3rd Party Exclusions

ExcludedRefs excludedRefs = AndroidExcludedRefs.createAppDefaults()

.instanceField("com.example.third.party.TheirClassOne", "fieldName")

.instanceField("com.example.third.party.TheirClassTwo", "fieldName")

.build();

LeakCanary.install(application, DisplayLeakService.class, excludedRefs);

Add in the additional exclusions

here

LeakCanary

20

Excluded Refs Builder Interface

public interface Builder { BuilderWithParams instanceField(String className, String fieldName); BuilderWithParams staticField(String className, String fieldName); BuilderWithParams thread(String threadName); BuilderWithParams clazz(String className); BuilderWithParams rootClass(String rootSuperClassName); ExcludedRefs build();}

LeakCanary

21

Known Android SDK Leaks are in AndroidExcludedRefs.java

Parts of an Excluded Leak:

Name (Manufacturer and SDK Range){ @Override void add(ExcludedRefs.Builder excluded) {

excluded.type of field <instance,static,root class, clazz>(“full.path.ClassToIgnore”, “field that was leaked")

.reason(“comment reason for the leak”); } } }

https://github.com/square/leakcanary/blob/master/leakcanary-android/src/main/java/com/squareup/leakcanary/AndroidExcludedRefs.java

Android Memory Leaks

Leak Canary Gotcha’s

22

Leak Cannary

23

Leak Canary on 6.0 and latter phones

Leak Cannary

24

Here is what you see in the Log 02-21 19:37:13.544 15173-15188/com.example.leakcanary D/LeakCanary: Could not attempt cleanup, leak storage not writable.02-21 19:37:24.592 15173-15189/com.example.leakcanary D/LeakCanary: Could not write to leak storage to dump heap.

Cause:

LeakCannary needs to write out heap dumps to external storage, so it needs the read and write external permissions, but on 6.0 this must be requested at run time

Fix:

use 1.4-beta1 or latter

enable storage permission when notification pops up notification

Leak Canary on 6.0 and latter phones

Android Memory Leaks

Fun with OQL

25

Leak Cannary

26

To find the referenced object in HPROF

To find your leaked object in the hprof file SELECT * FROM INSTANCEOF com.squareup.leakcanary.KeyedWeakReference a WHERE a.key = <Reference Key from Log>

SELECT * FROM INSTANCEOF android.app.Activity a WHERE a.mDestroyed = true

If you don’t have LeakCanary but do have hprof

27

28

Questions?

Special Thanks to Bottle Rocket Studios for providing meeting space and allowing me to share this material which is a simplified version of material presentation at a weekly code and tell .

More Resources https://realm.io/news/droidcon-ricau-memory-leaks-leakcanary/

https://github.com/square/leakcanary

top related