Android内存泄露抓取工具leakcanary

引言

“A small leak will sink a great ship.” – Benjamin Franklin

概述

某些对象的生命周期有限,当它们的工作完成以后,将会被GC回收。如果一个对象在其生命周期结束以后仍在内存中存在引用,将会导致内存泄露。当泄露积累过多,该应用将耗尽内存引起OOM,挂掉。

比如,在Activity.OnDestroy()方法被调用以后,这个activity的各种层级视图和它们关联的位图都应该被回收掉,如果一个后台运行的线程有该activity的引用,activity相对应的内存将不能被回收,这最终会导致OutOfMemoryError崩溃。

我们知道JAVA的内存回收由GC来回收,通常我们不用太关心内存的问题,但是对于资源比较紧张的手机系统来说,本来系统就不大,你还泄露了,这不是扯呢么,内存泄露的最终结果就是达到应用的内存阀值,应用崩溃。

为什么使用leakcanary

通常我们为了解决内存泄露的问题,一般有几个步骤

对于找内存泄露,之前的做法是连接AndroidStudio的Memory Monitor工具,,查看内存使用曲线

当进入一个界面内存自然升高,退出时内存没有下降,当再次进入时内存继续升高,如果出现这种情况就有可能内存泄露的可能。这种方式效率上比较低,并且有时会不准确。具体的可参考这篇文章 因此我们选择检测内存泄露高效并可以看到堆栈信息的leakcanary

leakcanary使用

leakcanary是square团队开源的一款检测并抓取android应用内存泄露的工具,优点

使用

Android Studio 下gradle依赖

dependencies { debugCompile ‘com.squareup.leakcanary:leakcanary-android:1.3.1’ releaseCompile ‘com.squareup.leakcanary:leakcanary-android-no-op:1.3.1’ }repositories {mavenCentral() }

在Application中

{ () {super.onCreate();LeakCanary.install(this); }}

如果gradle依赖不能区分deubg和release的话可以这样

compile ‘com.squareup.leakcanary:leakcanary-android:1.3.1′{ () {super.onCreate();if (BuildConfig.DEBUG) {//内存分析工具LeakCanary.install(this);} }}

LeakCanary.install() 会返回一个预定义的 RefWatcher,同时也会启用一个 ActivityRefWatcher,用于自动监控调用 Activity.onDestroy() 之后泄露的 activity。 配置很简单,当应用中发生内存泄露的时候会弹窗提示,并且在跟你应用程序同一个图标名字叫做Leaks的应用中就相应地记录

在Fragment中使用{ public static RefWatcher getRefWatcher(Context context) {ExampleApplication application = (ExampleApplication) context.getApplicationContext();return application.refWatcher; } private RefWatcher refWatcher; () {super.onCreate();refWatcher = LeakCanary.install(this); }}

使用 RefWatcher 监控 Fragment:

{ () {super.onDestroy();RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());refWatcher.watch(this); }}工作机制

leaktrace图形

并且logcat中会打出log

In com.example.leakcanary:1.0:1 com.example.leakcanary.MainActivity has leaked:* GC ROOT thread java.lang.Thread.<Java Local> (named ‘AsyncTask #1’)* references com.example.leakcanary.MainActivity$.os.AsyncTask)* leaks com.example.leakcanary.MainActivity instance* Reference Key: e71f3bf5-d786-4145-8539-584afaecad1d* Device: Genymotion generic Google Nexus 6 – 5.1.0 – API 22 – 1440×2560 vbox86p* Android Version: 5.1 API: 22* Durations: watch=5086ms, gc=110ms, heap dump=435ms, analysis=2086ms

但是有时这些log是不够的,找到内存泄露后,我们可以用MAT来分析内存泄露的原因,参考这篇文章

自定义

DisplayLeakActivity 有一个默认的图标和标签,你只要在你自己的 APP 资源中,替换以下资源就可。

res/ drawable-hdpi/__leak_canary_icon.png drawable-mdpi/__leak_canary_icon.png drawable-xhdpi/__leak_canary_icon.png drawable-xxhdpi/__leak_canary_icon.png drawable-xxxhdpi/__leak_canary_icon.png=”__leak_canary_display_activity_label”>MyLeaks</string></resources>保存leak trace

在 APP 的目录中,DisplayLeakActivity 保存了 7 个 dump 文件和 leak trace。你可以在你的 APP 中,定义 R.integer.__leak_canary_max_stored_leaks 来覆盖类库的默认值。

=”__leak_canary_max_stored_leaks”>20</integer></resources>总结

在项目中使用leakcanary可以极大的简化内存泄露分析的过程,并且最重要的可以提高程序的性能,避免OOM提高操作体验。

关于 Square

在开源世界里我们应该感谢那些为开源项目做出杰出贡献的个人和公司,而Square就是其中之一,Square已经将超过60多个项目提交到开源社区,贡献了25万行左右的代码。正是因为这样的公司个人,coder的世界正变的更美好。

而只有在充满了艰辛的人生旅途中,

Android内存泄露抓取工具leakcanary

相关文章:

你感兴趣的文章:

标签云: