1 .工具介绍
1.1使用Android Studio查看内存快照:
(1)可以查看对象对应的文件目录及内容,比如Bitmap可以看到对应的图片。
(2)可在InstanceView区右击可快速jump to source。
(3)不方便查看对象的最短引用链。
image.png
如图分为Heap Dump,Instance View, References三个区域。
其中Heap Dump区域:
Arrange by class:按照类进行分组
Arrange by package:按照包进行分组
Arrange by callstack:按照调用堆栈进行分组
说明:
Total Count 该类的实例总数
Sizeof 单个实例所占空间大小
Shallow Size 堆里所有实例大小总和(Heap Count * Sizeof)
Retained Size 该类所有实例所支配的内存大小
Heap Count 所选择的堆中该类的实例的数量
Depth GC根节点到所选实例的最短路径的深度
2.1使用MAT查看内存快照(推荐用):
(1)可以方便查看对象的对象的最短引用链。
(2)不方便定位对象对应的资源。
点击Histogram可显示内存快照文件
image.png
建议两个工具配合一起使用。
2.内存信息
通过adb查看当前进程的内存信息:
adb shell dumpsys meminfo <包名>
以我们产品为例:
adb shell dumpsys meminfo com.baidu.launcher
* daemon not running; starting now at tcp:5037
* daemon started successfully
Applications Memory Usage (in Kilobytes):
Uptime: 81529000 Realtime: 81529000
** MEMINFO in pid 11898 [com.baidu.launcher] **
Pss Private Private SwapPss Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 9685 9660 0 127 11520 9884 1635
Dalvik Heap 5341 5296 16 39 6069 3051 3018
Dalvik Other 3284 3284 0 36
Stack 64 64 0 0
Ashmem 23 0 0 0
Other dev 8 0 8 0
.so mmap 11878 420 8212 20
.apk mmap 1039 0 80 0
.dex mmap 22381 4 11124 4
.oat mmap 835 0 156 0
.art mmap 3184 2628 56 345
Other mmap 39 0 0 4
EGL mtrack 5226 5226 0 0
GL mtrack 8963 8963 0 0
Unknown 2490 2488 0 132
TOTAL 75147 38033 19652 707 17589 12935 4653
App Summary
Pss(KB)
------
Java Heap: 7980
Native Heap: 9660
Code: 19996
Stack: 64
Graphics: 14189
Private Other: 5796
System: 17462
TOTAL: 75147 TOTAL SWAP PSS: 707
Objects
Views: 33 ViewRootImpl: 1
AppContexts: 4 Activities: 0
Assets: 4 AssetManagers: 2
Local Binders: 41 Proxy Binders: 29
Parcel memory: 22 Parcel count: 87
Death Recipients: 1 OpenSSL Sockets: 4
WebViews: 0
SQL
MEMORY_USED: 287
PAGECACHE_OVERFLOW: 179 MALLOC_SIZE: 117
DATABASES
pgsz dbsz Lookaside(b) cache Dbname
4 200 2839/252/25 /data/user/0/com.baidu.launcher/databases/puffer.db
4 20 0/15/1 /data/user/0/com.baidu.launcher/databases/crabstat.db
4 56 3/35/5 /data/user/0/com.baidu.launcher/databases/duershow.db
4 12 0/0/0 (attached) temp
3.内存快照获取三种方式
3.1 通过android studio ----Memory Profiler
3.2 打开monitor(/Users/zhouwen/Library/Android/sdk/tools/monitor)
image.png
选取自己的应用进程名-->点击dump HPROF file按钮即可生成hprof文件。
3.3 通过adb shell am dumpheap也可以dump出hprof文件。
adb shell
cd data/local/tmp
am dumpheap <包名> output.hprof
➜ ~ adb shell
tb8765ap1_bsp_1g:/ # cd data/local/tmp
tb8765ap1_bsp_1g:/data/local/tmp # am dumpheap com.baidu.launcher output.hprof
4.内存泄露分析
4.1MAT(Memory Analyzer Tool)以我们项目为例:
4.1.1 内存快照获取
普遍的方式通过monitor dump对应的内存快照或者通过adb shell进入data/local/tmp目录下 am dumpheap 出对应应用的hprof文件。以我们项目为例,我们则通过跑稳定性当内存飙升到大于60M以上,会自动adb去dump一份内存快照上传到后台。
4.1.2 内存快照转换
/Users/zhouwen/Library/Android/sdk/hprof-conv input.hprof output.hprof
通过以上转换成mat可以解析的文件。
4.1.3 占比
image.png以上三个可能出现泄露问题的占比分布。
4.1.4 内存可能泄露的点
image.pngimage.png
如上图所示byte[]数组,Bitmap,NewBgView可能出现泄露。
4.1.5 通过搜索关键字可以搜索到相关泄露对象,比如Bitmap,Activity等。
image.pngimage.png
我自己一般分析内存步骤如下:
第一步:点击historgram按钮
image.png
通过Objects(对象数量)可以看出AlarmHomeCard和BaseCard对象数量比较多,可能存在泄露。
第二步:右击Objects数量比较多的class Name-->Merge Shortest Paths To Gc Roots-->exclude weak/soft references然后一个一个点开引用链分析。
以下是HomeCardGroup的第六个匿名内部类实例被handler引用着导致释放不了,对应NewBgView这个泄露点。
image.png
以下是TimerHomeCard的第一个匿名内部类实例被handler引用导致界面退出释放不了。
image.png
通过以上分析结合代码逻辑去看看到底是那个地方出现了内存泄露。
泄露原因及优化
原因:
上面两个内存泄露案例都有因为匿名内部类默认引用外部类,当界面关闭,导致当前界面一直释放不了,内存泄露。
解决办法:
将匿名内部类改成static,使其对外部类没有引用。
4.1.6参数说明
Objects:对象数量
Shallow Size:堆里所有实例大小总和(Heap Count * Sizeof)
Retained Size:该类所有实例所支配的内存大小
List objects:
with outgoing references: 列出这个对象被哪些对象引用
with ingoing references:列出这个对象持有哪些对象引用
Merge Shorts Path To GC Roots:
with all references:所有的引用。
exclude weak references: 去除弱引用。
exclude weak/soft references:去除弱/软引用(用的最多)。
其他就不列举了。
4.2 android studio分析(直接把内存快照拖至到as里)
这里就不介绍了,分析起来没Mat工具方便。
5.常见的内存泄露地方
5.1.Handler内存泄露,最好使用弱引用,释放时清除对应消息。
5.2.Cursor,File等使用完未关闭,及时关闭以便缓存数据及时回收。
5.3.过多的WebView,一个应用使用一个WebView并且最好放到单独的进程中。
5.4.注册对象未注销掉,导致界面一直释放不了。
5.5.及时释放容器对象。
5.6.匿名内部类持有外部引用。
5.7.单例中的Context生命周期大于本身Context生命周期
网友评论