使用 Android Studio 检测内存泄漏与解决内存泄漏问题

本文在腾讯技术推文上 修改 发布。  

http://wetest.qq.com/lab/view/63.html?from=ads_test2_qqtips&sessionUserType=BFT.PARAMS.195040.TASKID&ADUIN=913337456&ADSESSION=1468996652&ADTAG=CLIENT.QQ.5431_.0&ADPUBNO=26510

自从Google在2013年发布了Android Studio后,Android Studio凭借着自己良好的内存优化,酷炫的UI主题,强大的自动补全提示以及Gradle的编译支持正逐步取代Eclipse,成为主流的Android开发IDE。Android Studio在为我们提供了良好的编码体验的同时,也提供了许多对App性能分析的工具,让开发者可以更方便分析App性能。Google在IO大会上一直告诫开发者不要无节制的使用手机内存,要注意一些不良的开发习惯会导致App的内存泄漏。虽然如今网上检测App内存泄漏的文章汗牛充栋,但是要使用DDMS和MAT,不仅使用步骤复杂繁琐,而且要手动排查内存泄漏的位置,操作起来多有不便。其实Android Studio已经开始支持自动进行内存泄漏检查了,本文就带着大家一探其中的奥妙吧。

什么是内存泄漏 这个也是个面试常客,通俗来说,定义了的变量没使用,就是内存泄漏了。Android虚拟机的垃圾回收采用的是根搜索算法,还一种是程序计数器算法。GC会从根节点(GC Roots)开始对heap进行遍历。到最后,部分没有直接或者间接引用到GC Roots的就是需要回收的垃圾,会被GC回收掉。而内存泄漏出现的原因就是存在了无效的引用,导致本来需要被GC的对象没有被回收掉。

举个例子

mLeak是存储在静态区的静态变量,而Leak是内部类,其持有外部类Activity的引用。这样就导致Activity需要被销毁时,由于被mLeak所持有,所以系统不会对其进行GC,这样就造成了内存泄漏。

再举一个最常犯的例子

如果我们在在调用Singleton的getInstance()方法时传入了Activity。那么当instance没有释放时,这个Activity会一直存在。因此造成内存泄露。 解决方法可以将new Singleton(context)改为new Singleton(context.getApplicationContext())即可,这样便和传入的Activity没关系了。

内存泄漏的检测 打开Android Studio,编译代码,在模拟器或者真机上运行App,然后点击

,在Android Monitor下点击Monitor对应的Tab,进入如下界面

 在Memory一栏中,可以观察不同时间App内存的动态使用情况,点击

可以手动触发GC,点击

可以进入HPROF Viewer界面,查看Java的Heap,如下图

Reference Tree代表指向该实例的引用,可以从这里面查看内存泄漏的原因,Shallow Size指的是该对象本身占用内存的大小,Retained Size代表该对象被释放后,垃圾回收器能回收的内存总和。 下面我们以掌上道聚城客户端为例,来一探内存泄漏检测的方法。   打开Android Studio,编译代码,运行掌上道聚城,然后开始尽情的耍我们的App啦,然后就从Memory Monitor里面观察App的内存使用曲线,突然发现,纳尼!!!怎么内存使用越来越大了,这就很有可能是发生内存泄漏了,然后点击

手动进行GC,再点击

观看JavaHeap,点击Analyzer Task,Android Monitor就可以为我们自动分析泄漏的Activity啦,分析出来如下图所示

在Reference Tree里面,我们直接就可以看到持有该Activity的单例对象,直接定位到该单例中的代码,发现代码中出现了

和刚刚举得例子里出现的错误一模一样,我们修复了检查出的内存泄漏的问题,并将修复前和修复后的代码在相同的模拟器上运行并进行相同的操作,查看他们使用内存的情况,如下图所示

有内存泄漏的情况,占用内存约为43M

  修复了内存泄漏问题,占用内存为36M在修复了内存泄漏问题后,内存使用下降了16.3%!!!

最后补充一个我遇到的例子

优化代码后,明显解决了上述问题

最后,在掌握了Android Monitor的使用方法后,相信能在android开发的路上助各位一臂之力。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Bug生活2048

小程序云开发使用体验

这里发现直接更新有点慢,直接下载最新版然后覆盖比较快,打开最新的开发者工具之后会发现多了个云开发:

2932
来自专栏求索之路

从零开始仿写一个抖音App——Apt代码生成技术、gradle插件开发与protocol协议

本文首发于简书——何时夕,搬运转载请注明出处,否则将追究版权责任。交流qq群:859640274

914
来自专栏大数据和云计算技术

hdfs auditlog(审计日志)

hdfs审计日志(Auditlog)记录了用户针对hdfs的所有操作,详细信息包括操作成功与否、用户名称、客户机地址、操作命令、操作的目录等。对于用户的每一个...

773
来自专栏木宛城主

ASP.NET MVC 随想录——探索ASP.NET Identity 身份验证和基于角色的授权,中级篇

在前一篇文章中,我介绍了ASP.NET Identity 基本API的运用并创建了若干用户账号。那么在本篇文章中,我将继续ASP.NET Identity 之...

3426
来自专栏张善友的专栏

WCF Data Service QuickStart

开放数据协议(OData)是一个查询和更新数据的Web协议。OData是基于诸如HTTP和AtomPub的国际标准创建的,它提供了一个跨平台的数据通信的方案。O...

2047
来自专栏叁金大数据

自学Python八 爬虫大坑之网页乱码

  Bug有时候破坏的你的兴致,阻挠了保持到现在的渴望。可是,自己又非常明白,它是一种激励,是注定要被你踩在脚下的垫脚石!

681
来自专栏Flutter&Dart

DartVM服务器开发(第十六天)--Jaguar使用JWT

JWT(Json Web Token)Json网络令牌,是基于Json的开放标准,是一个用私钥编码和签名的JSON数据,由于它已签名,因此无法篡改数据。在存在私...

883
来自专栏JadePeng的技术博客

开源小工具 - swagger API访问代码生成器(js/typescript)

现在流行前后端分离,后端通常会使用swagger生成api文档,提供给前端的同事来调用,一般前端是查看这个文档,根据文档说明编写调用代码。其实,swagger已...

3176
来自专栏技术小讲堂

iBatis.Net(2):基本概念与配置

写完第一篇,有朋友给我发邮件,说想让我配合实例写会不会更好一些,可是呢,我觉得这就相当于那些北大的什么鸟给无辜的孩子们吃快餐一样,我是坚决反对那样的,知其然不知...

2717
来自专栏NetCore

Fluent Nhibernate之旅(五)--利用AutoMapping进行简单开发

Fluent Nhibernate(以下简称FN)发展到如今,已经相当成熟了,在Nhibernate的书中也相应的推荐了使用FN来进行映射配置,之前写的FN之旅...

2296

扫码关注云+社区