应用内存优化

概要

应用内存问题,大体可分为三种类型,内存泄漏、内存消耗过大、内存抖动等,内存异常会导致app卡顿、不流畅等,在整体内存不大的机器上甚至会影响系统性能,严重影响着用户体验,本文主要从以上三个方面来说明内存优化问题。

本文仅适用于应用内存优化。

内存泄漏异常

内存泄漏是指该回收的对象被其它对象持有,导致无法被回收,内存越用越多的现象。内存泄漏是开发者的噩梦,解决问题的关键就是切断异常的引用关系,实现对象正常回收。

怎么检测是否有内存泄漏呢?有两个方法。第一个方法为,使用ddms heap判断有无内存泄漏,打开ddms面板,选中对应的进程,点击 update heap 按钮,在heap面板上Cause GC,对app执行相关操作后,如果data object的数量一直呈上升趋势,那么则有内存泄漏。

第二个方法,利用dumpsys meminfo + 进程名,查看当前进程内存情况,对app操作后,如果内存一直上升,基本上也可以判断应用有内存泄漏。

常见的内存泄漏原因有:

  • 资源对象没有关闭(cursor、file、输入输出流等)
  • 注册对象没有反注册(广播、监听器等)
  • 重复bindService,没有unbindService
  • context、static变量导致
  • 重复载入字体文件导致

内存泄漏分析

Mat是分析内存泄漏的神兵利器,它能显示具体进程中对象的个数、引用关系、占用内存大小等等。通过引用关系,就能查找出异常引用。对象个数往往也是很重要的指标,如果某个activity个数大于1,很可能就存在内存泄漏。

假定场景,activity中只注册广播但未反注册,重复进入此activity或者旋转屏幕,此时抓取hprof文件,利用mat分析,整体流程如下:

  • 操作app一段时间,引发可能出现的内存泄漏,在ddms中,选中对应进程,点击 dump hprof file 按钮,生成hprof文件。
  • 调用hprof-conv origin.hprof goal.hprof,转换成mat能识别的文件
  • 用mat打开goal.hprof

Mat主要有三个重要面板,Histogram,列出每个类实例的个数。Leak Suspects,疑似内存泄漏报告。Dominator Tree,列出消费内存最多的对象。根据个人经验,从Histogram入手,最容易也最快就能找到问题所在。Leak Suspects,也较为方便可以查到问题所在。而从Dominator Tree入手,较难查找。针对模拟问题,从Histogram查看,并搜索特定包名(本例中特定包名为okunu),因为系统对象一般不会泄漏。

FirstActivity对象竟然有五个,这显示不对,右键选中FirstActivity,List objects,再选with incoming references,查看对象来源。

如上图,引用着FirstActivity对象的居然有这么多,FirstActivity无法释放,肯定是以上其中之一非法引用了FirstActivity,那么只能一一点开查看具体是哪个不良引用了。

这是一种查看不良引用的方式,还有另一种方式,查看gc路径。

第一种方式,直接查看持有FirstActivity引用的对象,最终找到未注册的广播监听器。第二种方式,查看FirstActivity的gc路径,最后找到LoadedApk对象中的mReceivers对象(在context注册广播里会在LoadedApk保存相关对象),所以也相当于找出了内存泄漏原因。

如果使用Leak Suspects查找内存泄漏原因,会稍显不直观,查看本例的Leak Suspects,发现占用最大的是char数组对象,于是打开Histogram,果然占用内存最大的即为char数组对象。

Char数组对象被FirstActivity的uiThread所引用,这明显不正常,还被好多个uiThread一同引用着,间接说明FirstActivity存在多个对象,它属于泄漏人员。那FirstActivity为啥泄漏呢?请见前文。

Mat确实是内存问题的神器,但因为内存对象的循环引用,信息太多,反而不太方便查找,mat往往给人这样的感觉,大海捞针。所以建议同学们使用Histogram面板,通过信息检索包名,快速定位,其它两个面板信息不直观,用处不是太大。最主要的两种查引用方式,with incoming reference(查看对象来源,能查看持有此对象引用的列表)和gc path(垃圾回收路径),多尝试,一定会有收获的。

内存开销大

内存开销过大,与内存泄漏有本质区别,内存泄漏是真正的bug,而且会内存越用越大,最终导致应用崩溃重启。内存开销过大,只是形容应用占用内存高,且一直维持在一定区间,并不会一直增大,在内存较小的机器上,内存开销过大会影响其它应用,影响总体性能,所以也是需要优化的。

解决内存开销大问题的关键点是,找到内存占用高的原因并想办法优化。但这并没有解决问题的明确套路或方法,并没有相关工具可以说清楚内存的构成(以前的android版本配合mat是可以的),最好的方法是删代码,使用排除法来找优化点,针对app常见的内存大户,比如说图片等,删除代码后查看内存情况,往往会有收获。

此类问题最重要的还是平时养成较好的编码习惯,减少内存使用,像帧动画之类的可以不用就尽量不用。

内存抖动

内存抖动,是指在使用过程中迅速申请内存又迅速释放,导致gc频繁,app卡顿,影响用户体验。在Android studio上可以动态查看内存使用情况,非常方便地就能定位内存抖动。内存抖动常常能见到如下波形:

此时也能通过log定位,搜索关键字gc,往往会有如下log

此类情况常常发生在循环中,比如字符串拼接,在循环中构造bitmap对象等等。在图片处理应用中也可能发生这种情况,申请内存和释放内存频率过高,导致异常。这类问题是能够很好地避免的,如果逻辑需要,必然存在大量内存申请又释放的问题,那就只能采用缓存方式了,将所需资源缓存起来,不释放或在特定时间点再释放,用空间换取应用的流畅性。

总结

以上三类内存问题均可以通过良好编码习惯避免的,了解常见的内存泄漏原因,清楚内存泄漏形成原理,在日常工作中注意及时释放资源等,都是可以避免的。mat信息非常庞大,日常多看看,也有助于解决内存泄漏等问题。而内存开销大,有时是一件很检验代码熟悉程度的工作,优化有一定难度,需要沉下心来。内存抖动反而是以上三种中最容易解决的问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容