Android LeakCanary内存泄露分析

Andorid LeakCanary内存泄露分析

LeakCanary是Square出的一个直接在移动端可视化查看分析内存泄露的库。

  

Square这家公司牛逼了,很多大名鼎鼎的Android开源库都是这家公司贡献了,比如OkHttp,Retrofit,Picasso,otto等等,具体可以上Square的Gihub账号查看。

1,先感官认识下使用过程

运行leakcanary-sample工程
img
按照demo上的说明,点击start new asynctask然后旋转屏幕,这样可以多操作几次。过了一分钟左右在通知栏会弹出一个消息,就是内存泄露的通知了。
img
点击进去就是内存泄露的分析页面了,看起来挺精确的。
img

2,leakcanary使用&demo代码简单分析

官方的readme已经说明了使用方法
build.gradle里引用库

1
2
3
4
5
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
}

然后在工程的自定义Application类里

1
2
3
4
5
6
7
public class ExampleApplication extends Application {

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

就可以了。。

demo里面基本只有MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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();
}
}

简单来说就是点下按钮然后旋转屏幕,然后再点下按钮,在旋转屏幕。
泄露的原因跟hanlder常见的泄露原因一样,就是java的非静态匿名内部类会引用外部类,每次开启一个匿名的AsyncTask后再旋转屏幕时,因为匿名AsyncTask的引用导致没法回收。

3 原理简单分析

leakcanary通过开启后台线程检查引用是否清除,然后调用GC,再把 heap 内存 dump 到 APP 对应的文件系统中的一个 .hprof 文件中, 在开另外一个线程通过调用HAHA(Headless Android Heap Analyzer 也是Square开源的库,用来分析.hprof,这样看来leakcanary跟mat基本是一样的),然后再发个到通知栏消息,点击把结果展示出来。网上有篇介绍的文章。 LeakCanary 中文使用说明

就酱