我是靠谱客的博主 粗犷冰棍,最近开发中收集的这篇文章主要介绍应用内存泄露问题分析实例,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

内存泄露,这个应用开发中比较容易出现的问题,由于短时间内难以测出来一般都比较难以发现,只能靠开发者的警觉性来避免,长时间的Monkey测试就成为一个可行的手段。

Monkey测试能给出一个直观的内存变化曲线和日志,GC日志在内存紧张时都会打印出测试进程的内存信息。往往报错信息也会指明是 java.lang.OutOfMemoryError但是报这个异常的地方往往并不是内存泄露的位置,它只是比较倒霉正好申请内存发现不足了。

直接找重点GC日志类似这样:

 I art     : Starting a blocking GC Alloc
 I art     : Starting a blocking GC Alloc
 I art     : Waiting for a blocking GC Alloc
 I art     : Alloc sticky concurrent mark sweep GC freed 5223(480KB) AllocSpace objects, 5(100KB) LOS objects, 1% free, 189MB/192MB, paused 2.153ms total 35.644ms
 I art     : WaitForGcToComplete blocked for 21.733ms for cause Alloc
 I art     : Starting a blocking GC Alloc

相信网上解释这几句日志的博客已经很多了,就是现在已用内存189M上限是192M,应用下一次申请超过剩余操作限制了就OOM了。

首先确认信息是否符合系统设定

查看系统设置单个进程的内存上限

adb shell
root@125:/ # getprop|grep heapgrowthlimit
[dalvik.vm.heapgrowthlimit]: [192m]

没错就是配置的192M,你的应用消耗的太多了,肯定是有内存泄露了的。

那么怎么查找问题呢,通过这个日志直接分析不到问题,只能根据日志看出应用的大致操作流程,不过Monkey几万次估计所有逻辑都走到了,还是对整个应用内容的使用情况进行检查。

Android上应用开发常见的内存泄露的类型可以看看大神写的http://blog.csdn.net/u010687392/article/details/49909477

其实自从Bitmap的内存分配到java层之后这一类很容易搞定了,用弱引用的缓存直接就安了,这个直接全代码搜索一下挨个改就行了;

其他的同样显性的BraodcastReceiver,ContentObserver,File,Cursor,Stream这一类全代码搜索改就行了;

剩下的比较难找的就是Activity的泄露同时也是应用主要的内存泄露问题,这个如果对代码很熟悉也可以对代码中所有的context、handler等搜索处理,但是如果封装层次比较深模块代码量比较大的情况下,会花费较长的时间。

首先可以用adb shell dumpsys meminfo package name看看当前进程的内存使用情况

Applications Memory Usage (kB):
Uptime: 774504 Realtime: 774504


** MEMINFO in pid 5592 [package namer] **
                   Pss  Private  Private  Swapped     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap     9076     8980        0        0    12776    12483      292
  Dalvik Heap    12276    12200        0        0    14499    13738      761
 Dalvik Other      956      956        0        0
        Stack      328      328        0        0
      Gfx dev     3926     3056        0        0
    Other dev        5        0        4        0
     .so mmap     2320      464       60        0
    .apk mmap      136        0       16        0
    .ttf mmap      346        0      204        0
    .dex mmap     2524        0     2520        0
    .oat mmap     4493        0     1756        0
    .art mmap     2465     1196      628        0
   Other mmap       51        4       40        0
   EGL mtrack    28224    28224        0        0
      Unknown      233      232        0        0
        TOTAL    67359    55640     5228        0    27275    26221     1053


 Objects
               Views:      271         ViewRootImpl:        1
         AppContexts:        7           Activities:        1
              Assets:        3        AssetManagers:        3
       Local Binders:       22        Proxy Binders:       32
       Parcel memory:        8         Parcel count:       34
    Death Recipients:        0      OpenSSL Sockets:        0


 SQL
         MEMORY_USED:     1206
  PAGECACHE_OVERFLOW:      946          MALLOC_SIZE:       62


 DATABASES
      pgsz     dbsz   Lookaside(b)          cache  Dbname
         1     1673            281     834/125/25  /data/data/package name/databases/sqlit.db

如果此时这里的Activities与目前应用的运行状态不一致,比如目前退出了应该为零但是这里还有数值,很显然就是有Context泄露了(其实这里还能看到很多其他内存数据),这时候就可以使用MAT工具进行分析。

先生成一个hprof文件,然后用MAT工具打开,直接在总览界面选择

Histogram: Lists number of instances per class

这时会将所有当前对象及其数量Heap大小一起列出来,非常的多,可以直接输入Activity或者其他关键字进行搜索。

如果其中的Objects数目与当前应用运行情况不一致就是有问题的地方。

在此条记录上右键选择Merge Shortest Paths to GC Roots --> with all references就可以列出当前对象到GC Root之间的最短引用链,找到并打断这个引用关系就是我们工作

这个栗子由于项目关系就不能贴上具体代码和截图了,最终是在一个单例中发现了一个HashMap引用了一系列的Context在里面。

好了,分析完毕,为了最小的改动,直接将HashMap修改成WeakHashMap,这个东西是在检测到某个key值没有被引用的情况下会回收掉entry,最后检查一下它的get方法如果为空会不会有问题,看一遍没有问题。


问题解决,虽然看起来分析的很愉快,但是在项目的关键时期大半夜看这个还是很伤的,开发者还是需要在写代码的时候就注意内存泄露的问题,尤其是Context的使用,没事多用Application的Context,实在不行也要注意及时主动置空和弱引用。


最后

以上就是粗犷冰棍为你收集整理的应用内存泄露问题分析实例的全部内容,希望文章能够帮你解决应用内存泄露问题分析实例所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(41)

评论列表共有 0 条评论

立即
投稿
返回
顶部