A list,

LeakCanary is a foolproof and visual memory leak analysis tool


Two, use method

Try to add the following dependencies to build.grade in your app

 dependencies {
   debugCompile 'com. Squareup. Leakcanary: leakcanary - android: 1.3.1'/ / or 1.4 beta1 releaseCompile'com. Squareup. Leakcanary: leakcanary - android - no - op: 1.3.1'/ / or 1.4 beta1testCompile 'com. Squareup. Leakcanary: leakcanary - android - no - op: 1.3.1' // or 1.4-beta1
 }
Copy the code

Add code similar to the following to your Application

public class ExampleApplication extends Application {
  @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); }}Copy the code


At this point, you can detect a memory leak in your Activity. Its implementation principle is to set up the Application of ActivityLifycycleCallbacks () method to monitor all the Activity’s lifecycle callback. The internal implementation code is:

public final class ActivityRefWatcher {
    private final ActivityLifecycleCallbacks lifecycleCallbacks = 
                   new ActivityLifecycleCallbacks() { public void onActivityCreated(Activity activity, Bundle savedInstanceState) { } public void onActivityStarted(Activity activity) { } public void onActivityResumed(Activity activity) { } public void onActivityPaused(Activity activity) { } public void onActivityStopped(Activity activity) { } public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } public void onActivityDestroyed(Activity activity) { ActivityRefWatcher.this.onActivityDestroyed(activity); }}; private final Application application; private final RefWatcher refWatcher; public static void installOnIcsPlus(Application application, RefWatcher refWatcher) {if(VERSION.SDK_INT >= 14) { ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher); activityRefWatcher.watchActivities(); }}... }Copy the code


Detect more memory leaks

First we need to get a RefWatcher for subsequent monitoring of objects that might be found leaking

public class MyApplication extends Application {
    private static RefWatcher sRefWatcher;

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

    public static RefWatcher getRefWatcher() {
        returnsRefWatcher; }}Copy the code

Monitor an object that may have a memory leak

MyApplication.getRefWatcher().watch(sLeaky);
Copy the code


4. Objects to be monitored

By default, the Activity is checked. Another important object to monitor is the Fragment instance. Because it is as likely as an Activity instance to hold a large number of views and resources (such as bitmaps) that views require, add the following implementation monitoring to the fragment.onDestroy () method:

public class MainFragment extends Fragment {
    @Override
    public void onDestroy() { super.onDestroy(); MyApplication.getRefWatcher().watch(this); }}Copy the code


Other objects that can also be monitored

  • BroadcastReceiver
  • Service
  • Other objects with a life cycle
  • Directly or indirectly holding a large memory footprint (that is, retaining a large Heap value)


Five, when to monitor

A memory leak, in short, is a memory leak caused by an object that cannot be released at the time it should be released because it is held by other objects.

Therefore, monitoring needs to be set up when an object is released (soon), such as the onDestroy() method for activities and fragments.

Note, must not during initialization!!

For example, monitoring an Activity, placing onCreate() would be a big mistake because it would receive a leak notification for the Activity every time.


6. Solution to memory leakage

Common solutions:

  • Try to useApplicationtheContextNot the Activity
  • Use weak or soft references
  • Manually set null to dereference
  • Set the inner class to static without implicitly holding external instances
  • Registration and de-registration occur in pairs, and de-registration takes place during the lifetime of the object
  • If you do not have permission to modify, such as the system or a third-party SDK, then use reflection to resolve the holding


Add exceptions

There are special cases where we need to ignore something, and that’s when we need to add exceptions. Such as ExampleClass. ExampleField (some kind of a member variable) can lead to memory leaks, we want to ignore, the following actions:

// ExampleApplication is defined in "Customizing and using the no-op dependency"
public class DebugExampleApplication extends ExampleApplication {
  protected RefWatcher installLeakCanary() {
    ExcludedRefs excludedRefs = AndroidExcludedRefs.createAppDefaults()
        .instanceField("com.example.ExampleClass"."exampleField")
        .build();
    returnLeakCanary.install(this, DisplayLeakService.class, excludedRefs); }}Copy the code


Eight, how to achieve

LeakCanary has actually done an automatic Heap dump on this machine and then analyzed the resulting hprof file to show the results. The procedure is basically the same as manual MAT analysis.


Ix. How not to affect external APK

LeakCanary does affect application performance, especially heap dump operations, but this is something That Square has already considered when adding dependencies

debugCompile 'com. Squareup. Leakcanary: leakcanary - android: 1.3.1'/ / or 1.4 beta1 releaseCompile'com. Squareup. Leakcanary: leakcanary - android - no - op: 1.3.1'/ / or 1.4 beta1testCompile 'com. Squareup. Leakcanary: leakcanary - android - no - op: 1.3.1'/ / or 1.4 beta1Copy the code

ReleaseCompile and testCompile are obviously different from debugCompile. Their dependencies belong to NOOP operations.

NOOP means No Operation Performed. Common compiler techniques detect no-operation instructions and weed them out for optimization purposes.

Therefore, once the releaseCompile and testCompile dependencies are configured, there is no need to worry about the performance of the external version.


Android Memory Leak detection tool: LeakCanary