博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android内存优化(六)LeakCanary使用详解
阅读量:4223 次
发布时间:2019-05-26

本文共 3890 字,大约阅读时间需要 12 分钟。

相关文章 

 

1.概述

如果使用MAT来分析内存问题,会有一些难度,并且效率也不是很高,对于一个内存泄漏问题,可能要进行多次排查和对比。 

为了能够简单迅速的发现内存泄漏,Square公司基于MAT开源了。 

2.使用LeakCanary

首先配置build.gradle:

dependencies {   debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.2'   releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.2' }
  • 1
  • 2
  • 3
  • 4

接下来在Application加入如下代码。

public class LeakApplication extends Application {
@Override public void onCreate() { super.onCreate(); if (LeakCanary.isInAnalyzerProcess(this)) {
//1 // This process is dedicated to LeakCanary for heap analysis. // You should not init your app in this process. return; } LeakCanary.install(this); }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

注释1处的代码用来进行过滤操作,如果当前的进程是用来给LeakCanary 进行堆分析的则return,否则会执行LeakCanary的install方法。这样我们就可以使用LeakCanary了,如果检测到某个Activity 有内存泄露,LeakCanary 就会给出提示。

3.LeakCanary应用举例

第二节的例子代码只能够检测Activity的内存泄漏,当然还存在其他类的内存泄漏,这时我们就需要使用RefWatcher来进行监控。改写Application,如下所示。

public class LeakApplication extends Application {
private RefWatcher refWatcher; @Override public void onCreate() { super.onCreate(); refWatcher= setupLeakCanary(); } private RefWatcher setupLeakCanary() { if (LeakCanary.isInAnalyzerProcess(this)) { return RefWatcher.DISABLED; } return LeakCanary.install(this); } public static RefWatcher getRefWatcher(Context context) { LeakApplication leakApplication = (LeakApplication) context.getApplicationContext(); return leakApplication.refWatcher; }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

install方法会返回RefWatcher用来监控对象,LeakApplication中还要提供getRefWatcher静态方法来返回全局RefWatcher。

最后为了举例,我们在一段存在内存泄漏的代码中引入LeakCanary监控,如下所示。

public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LeakThread leakThread = new LeakThread(); leakThread.start(); } class LeakThread extends Thread { @Override public void run() { try { Thread.sleep(6 * 60 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } } @Override protected void onDestroy() { super.onDestroy(); RefWatcher refWatcher = LeakApplication.getRefWatcher(this);//1 refWatcher.watch(this); }}
  • 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

MainActivity存在内存泄漏,原因就是非静态内部类LeakThread持有外部类MainActivity的引用,LeakThread中做了耗时操作,导致MainActivity无法被释放。关于内存泄漏可以查看这篇文章。 

在注释1处得到RefWatcher,并调用它的watch方法,watch方法的参数就是要监控的对象。当然,在这个例子中onDestroy方法是多余的,因为LeakCanary在调用install方法时会启动一个ActivityRefWatcher类,它用于自动监控Activity执行onDestroy方法之后是否发生内存泄露。这里只是为了方便举例,如果想要监控Fragment,在Fragment中添加如上的onDestroy方法是有用的。 
运行程序,这时会在界面生成一个名为Leaks的应用图标。接下来不断的切换横竖屏,这时会闪出一个提示框,提示内容为:“Dumping memory app will freeze.Brrrr.”。再稍等片刻,内存泄漏信息就会通过Notification展示出来,比如三星S8的通知栏如下所示。 

Notification中提示了MainActivity发生了内存泄漏, 泄漏的内存为787B。点击Notification就可以进入内存泄漏详细页,除此之外也可以通过Leaks应用的列表界面进入,列表界面如下图所示。

内存泄漏详细页如下图所示。 

点击加号就可以查看具体类所在的包名称。整个详情就是一个引用链:MainActiviy的内部类LeakThread引用了LeakThread的this$0this$0的含义就是内部类自动保留的一个指向所在外部类的引用,而这个外部类就是详情最后一行所给出的MainActiviy的实例,这将会导致MainActivity无法被GC,从而产生内存泄漏。

除此之外,我们还可以将 heap dump(hprof文件)和info信息分享出去,如下图所示。 

device-2017-09-02-181759_副本.png

需要注意的是分享出去的hprof文件并不是标准的hprof文件,还需要将它转换为标准的hprof文件,这样才会被MAT识别从而进行分析,关于MAT可以查看这篇文章。

解决方法就是将LeakThread改为静态内部类。

public class MainActivity extends AppCompatActivity {
... static class LeakThread extends Thread { @Override public void run() { try { Thread.sleep(6 * 60 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } }...}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

再次运行程序LeakThread就不会给出内存泄漏的提示了。

参考资料 

《高性能Android应用开发》 
 
 
 

转载自:https://blog.csdn.net/itachi85/article/details/77826112

你可能感兴趣的文章
通知 | 2020年度“RONG”奖学金入围答辩名单公布
查看>>
2020 Kaggle年度报告发布:美国公司最容易「人均百万」,90%数据科学家坚持终生学习...
查看>>
基于Dijkstra算法的武汉地铁路径规划!(附下载)
查看>>
外卖平台涉嫌大数据杀熟,处理不能“自说自话”
查看>>
AI把爱豆变胖视频火遍B站,我们找到了背后的技术团队:你是怎么把刘亦菲变胖的?...
查看>>
斯坦福被炮轰:用算法分配5000支新冠疫苗,医护人员只有7支
查看>>
人工智能基准(Benchmarking)再思考
查看>>
原创 | 一文了解人工智能对精准扶贫的作用及数字乡村建设现状
查看>>
神器 jupyter,终于来了!
查看>>
白硕:区块链技术与数据隐私(附视频)
查看>>
学好机器学习必备这12条经验 !(附资料)
查看>>
张甜甜:在实践中迈进数据科学领域 | 优秀毕业生专访
查看>>
盘点数据科学20个最好的Python库(附链接)
查看>>
“达观杯”NLP算法大赛再启航,丰厚奖金、直通Offer等你来拿!
查看>>
教你用10行Python代码实现目标检测(附代码)
查看>>
19个超赞的数据科学和机器学习工具,编程小白必看!(附资料)
查看>>
报名 | 清华大学海外学者短期讲学:创新创业发展课程
查看>>
Python用5000+条数据为你分析《我不是药神》登顶原因!(附代码)
查看>>
这5个机器学习项目你不可错过!(附代码)
查看>>
放弃80万年薪,这两位清华博士想让法律人用上真正的AI!
查看>>