常用内存分析命令及常见内存泄露分析思路

adb 命令

使用android shell命令查看内存使用情况

单位为千字节 KB

adb shell dumpsys meminfo pkgname

示例

adb shell dumpsys meminfo top.ftas.demo.leaked
# 查看 Java Heap 大小
adb shell dumpsys meminfo top.ftas.demo.leaked|grep Java\ Heap
# 查看 Native Heap 大小
adb shell dumpsys meminfo top.ftas.demo.leaked|grep Native\ Heap

内存动态监控

watch -n 0.5 adb shell dumpsys meminfo top.ftas.demo.leaked

一般需要重点关注下面:
Heap Alloc 列,TOTAL 行(或者 App Summary 的 Java Heap ) - 数值的大小
Activities - 数值的大小
Views - 数值的大小
AppContexts - 数值的大小

通过快速输出 Activities 的数量,检查出是否有 Activities 泄露

adb shell dumpsys meminfo 应用包名 |grep Activities

示例

adb shell dumpsys meminfo top.ftas.demo.leaked |grep Activities
AppContexts:       11           Activities:        8
AppContexts:       12           Activities:        9

快速获取当前 Activity ,确定泄露位置

adb shell dumpsys activity activities | sed -En -e '/Running activities/,/Run #0/p'

在当前进程中抓取当前进程的hprof信息

adb shell am dumpheap pid或者pkgName file

获取 pid 命令

adb shell ps | grep pkgName

示例

#获取 pid
adb shell ps |grep top.ftas.demo.leake
#生成 hprof
adb shell am dumpheap 9686 /data/local/tmp/test-leaked-pid.hprof
#生成 hprof
adb shell am dumpheap top.ftas.demo.leaked /data/local/tmp/test-leaked-pkg.hprof
#下载 hprof
adb pull /data/local/tmp/test-leaked-pkg.hprof
#hprof 转成 mat 识别的格式
hprof-conv test-leaked-pkg.hprof test-leaked-pkg.mat.hprof 
u0_a876   9686  782   1785284 98684 SyS_epoll_ 0000000000 S top.ftas.demo.leaked

在当前进程使用 Debug.dumpHprofData 获取 hprof 文件

Debug.dumpHprofData(path);

android-developer-dumpHprofData

示例:

File hprofFile = new File(getExternalCacheDir(), "DumpHprofDataActivity-dumpHprofData.hprof");
String path = hprofFile.getAbsolutePath();
Log.e("DumpHprofDataActivity", "hprofFile.getAbsolutePath = " + path);
try {
    Debug.dumpHprofData(path);
} catch (IOException e) {
    Log.e("DumpHprofDataActivity", Log.getStackTraceString(e));
}
#从缓存中拉取 hprof 文件
adb pull /storage/emulated/0/Android/data/top.ftas.demo.leaked/cache/DumpHprofDataActivity-dumpHprofData.hprof
#hprof 文件格式转换
hprof-conv DumpHprofDataActivity-dumpHprofData.hprof DumpHprofDataActivity-dumpHprofData.mat.hpro

jhat

分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言 

# 生成 hprof
adb shell am dumpheap top.ftas.demo.leaked /data/local/tmp/test-leaked-pkg.hprof
# 下载 hprof
adb pull /data/local/tmp/test-leaked-pkg.hprof
# 将 HPROF 文件从 Android 格式转换为 Java SE HPROF 格式
hprof-conv test-leaked-pkg.hprof test-leaked-pkg.mat.hprof 
# 启动 jhat 服务器,分析 hprof 文件
# 或 jhat -J-Xmx512m <heap dump file>
jhat test-leaked-pkg.mat.hprof
# 访问本地 jhat 站点
open http://localhost:7000/

分析内存泄露常见思路

mat 分析 - Histogram - Activity 泄露

进入 Histogram
Class Name 中输入 Activity 进行过滤
点击 Objects 排序
重点关注 Objects 字段, 哪些 Activity 过多
找到 Objects 大于 1 的,一般就有泄露的可能
右键有泄露可能的 Activity,按如下方式确定泄露路径
Merge Shortes Paths to GC Roots
exclude all phantom/weak/soft etc.references
其中最下方的 Total:7 entries 是总泄露数
依次展开任意一行,可以看到完整的泄露路径。其中最顶部是 GC Root。 

mat 分析 - Histogram - Shallow Heap 排序

一般占比最高的是 byte[] 或者 char[]
右键 byte 数组
Merge Shortes Paths to GC Roots
exclude all phantom/weak/soft etc.references
按 Ref.Shallow Heap 排序,确认 Ref.Shallow Heap 占用内存较多的对象是否合理 

Android Studio Profiler - Memory Profiler Activity 内存泄露分析法

官方文档:memory-profiler

先捕获堆转储,请点击 Memory Profiler 工具栏中的 Dump Java heap 图标
Filter 中输入 Activity 回车
点击 Allocations 按实例数排序
点击 Allocations 数值较多的 Activity
右侧 『Instance View』面板中会出现所有实例对象(观察 Depth,比如为 5),点击任意一个实例对象
右下侧『References』两板中会出现引用链
依次展开『References』,找到泄露源。特别注意,由于有循环引用,这里一定要按照 Depth 『5 4 3 2 1 0』的顺序展开。否则会无限循环,无穷尽也。 

 

CPU Profiler

官方文档:cpu-profiler

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章