Android之内存泄露LeakCanary检测

来源:互联网 发布:域名有什么作用 编辑:程序博客网 时间:2024/05/16 18:40

之前有一篇文章提到内存泄露,如果你还不知道安卓中内存泄露是怎么回事,可以去看:
Android之内存泄露与内存管理
http://blog.csdn.net/u014639129/article/details/52735850。

那么知道了内存泄露,那么如何避免呢?或者说,我们怎么确定我们的APP没有内存泄露的现象呢?

下面,我们使用LeakCanary来检测并且找出内存泄露的bug。

下面,我们首先模拟一个简单的内存泄露,static静态常量(长生命周期对象)引用Activity(相对static来说,属于短生命周期对象)导致的内存泄露。

public class Constant {    public static List<Activity> activityList  = new ArrayList<>();    public static void add(Activity activity){        activityList.add(activity);    }}

这是一个Constant常量类,可以看到我们用一个static的List去装载Activity。

public class MainActivity extends AppCompatActivity {    private List<String> list = new ArrayList<>();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        for(int i = 0; i < 100000; i ++){//这里for循环,仅仅是为了看到内存的明显的增长            list.add(new String(i+""));        }        Constant.add(this);//这里把Activity加入到static常量数组    }}

代码解释的很清楚也很简单。

我们运行APP,关闭,运行,关闭,反复执行几次

这里写图片描述

内存持续增长,而没有下降

这里写图片描述

甚至还出现了无响应

我们从代码里,很明显的能找到这样的一个内存泄露:
list 引用着activity,即使activity被ondestory()了,依然不能释放内存。

如果我们不知道哪里出现了内存泄露,我们如何准确定位找到bug呢?上面已经提到LeakCanary了,没错。

那么,我先运行使用了LeakCanary执行后的效果。

先打开应用,然后关闭,等上数秒的时间,通知栏会弹出通知

这里写图片描述

点击通知,弹出
这里写图片描述

这个结果,相信大家都看明白了吧?
也就是Constant.activityList静态对象引用着MainActivity实例对象。

那么,我们的代码要怎么做呢?非常简单

首先加入依赖包

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

然后在Application初始化一下

public class App extends Application {    @Override    public void onCreate() {        super.onCreate();        LeakCanary.install(this);    }}

这样就可以了。

心里有底了吗?我们再做一个单例导致的内存泄露实验吧。

public class DataModel {    private static DataModel sInstance;    private TextView textView;    public static DataModel getInstance() {        if (sInstance == null) {            sInstance = new DataModel();        }        return sInstance;    }    public void setTextView(TextView textView) {        textView = textView;    }}
public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TextView textView = (TextView) findViewById(R.id.tv);        DataModel.getInstance().setTextView(textView);    }}

这里写图片描述

有看到有一条引用链:
sInstance(长生命周期)–>mRetainedTextview->mContext->mBase->MainActivity(短生命周期)

有兴趣的同学,可以知己去测试一些常见的内存泄露哦。

一:LeakCanary到底是什么?
LeakCanary项目是大名鼎鼎的square公司为Java&Android开发提供的一个自动检测内存泄漏的工具,现在很多项目都在引入来提高代码质量,减少不必要的内存泄漏。尽管Java有垃圾回收机制,但是一些无意识的代码经常会导致对象的引用存在超过其生命周期。

二:LeakCanary是怎么运作的?
1.检测一个对象是否是可疑的泄漏对象。
2.如果第一步发现可疑对象,dump内存快照,通过分析.hprof文件,确定怀疑的对象是否真的泄漏。
3.将分析的结果展示。

0 0
原创粉丝点击