常用內存分析命令及常見內存泄露分析思路

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

 

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