一、核心命令總覽
工具 / 命令 | 用途 | 示例 |
---|---|---|
adb shell dumpsys meminfo | 查看設備全局內存狀態 | adb shell dumpsys meminfo |
adb shell dumpsys meminfo <package> | 獲取應用詳細內存分類統計 | adb shell dumpsys meminfo com.example.app |
adb shell top | 動態查看進程內存和 CPU 占用 | adb shell top -m 10 -n 1 |
adb shell am dumpheap | 導出 Java Heap.hprof 文件 | adb shell am dumpheap com.example.app /data/local/tmp/app.hprof |
adb pull | 將 hprof 文件導出至本地分析 | adb pull /data/local/tmp/app.hprof ./ |
adb shell setprop libc.debug.malloc | 打開 native 分配追蹤 | adb shell setprop libc.debug.malloc backtrace |
adb shell am send-trim-memory | 模擬系統觸發內存回收 | adb shell am send-trim-memory com.example.app TRIM_MEMORY_UI_HIDDEN |
二、核心命令詳解與用例
1. adb shell dumpsys meminfo
(全局內存)
作用:查看設備整體內存狀態,包括系統剩余內存、應用內存占用排名等。
adb shell dumpsys meminfo
關鍵輸出解析:
Total RAM: 5,789,412K (status normal)Free RAM: 1,234,567K ( 238,456K cached pss + 12,345K kernel)Used RAM: 3,456,789K (2,123,456K used pss + 1,333,333K kernel)Lost RAM: 987,654KZRAM: 123,456K physical used for 456,789K in swap (500,000K total swap)
字段 | 說明 |
---|---|
Total RAM | 設備物理內存總量 |
Free RAM | 可用內存 = 緩存進程內存 + 內核保留內存 |
Used RAM | 已用內存 = 應用實際使用量(PSS) + 內核占用 |
Lost RAM | 內存碎片或無法統計的內存 |
ZRAM | 壓縮交換分區使用情況(若啟用) |
進程內存分類:
Total PSS by OOM adjustment:543,052K: Native # 原生進程286,850K: System # 系統核心進程381,177K: Persistent # 常駐進程(如SystemUI)344,152K: Visible # 可見進程245,108K: Perceptible # 可感知進程(如后臺服務)91,710K: Backup # 備份進程52,148K: Cached # 緩存進程
內存類型分布:
Total PSS by :510,454K: Native # Native代碼內存247,842K: Dalvik # Java堆內存154,596K: .art mmap # ART運行時128,773K: .oat mmap # AOT編譯代碼20,620K: Gfx dev # 圖形內存
異常狀態檢測:
-
Low內存狀態:
status low
表示系統處于內存緊張狀態 -
ZRAM高使用:695MB/2.3GB的交換空間使用量(壓縮比≈3.6倍)
-
可疑進程:
com.tencent.mm:push
(73MB) 占用B Servicescom.xiaomi.market
(85MB) 占用Perceptible
建議腳本:
# 監控高內存進程
adb shell dumpsys meminfo | grep -E "K: (Native|System|Persistent|Visible)" -A 3# 追蹤ZRAM變化
watch -n 1 'adb shell dumpsys meminfo | grep "ZRAM"'
2. adb shell dumpsys meminfo <package>
(應用詳情)
作用:獲取指定應用的內存詳細分布,包括 Java/Native/Graphics 等。
adb shell dumpsys meminfo com.example.app
輸出示例:
Applications Memory Usage (in Kilobytes):
Uptime: 15123 Realtime: 34253** MEMINFO in pid 12345 [com.example.myapp] **Pss Private Private Swapped Heap Heap HeapTotal Dirty Clean Dirty Size Alloc Free------ ------ ------ ------ ------- ------- -------Native Heap 8848 8844 0 0 32768 11234 21534Dalvik Heap 7832 7828 0 0 40960 15876 25084Dalvik Other 1523 1500 0 0Stack 96 96 0 0Ashmem 2 0 0 0Gfx dev 2492 2488 0 0Other dev 28 28 0 0.so mmap 4213 8 3324 0.apk mmap 1634 0 1234 0.ttf mmap 34 0 34 0.dex mmap 2090 0 2090 0Other mmap 228 0 4 0EGL mtrack 1020 1020 0 0GL mtrack 1832 1832 0 0Unknown 2202 2200 0 0TOTAL 43102 32844 6986 0 73728 27110 46618
字段逐項解釋
列名 | 含義 |
---|---|
Pss Total | Proportional Set Size,總共享后按比例分配的內存大小(關鍵指標) |
Private Dirty | 只屬于當前進程且被修改的內存頁,實際的獨占內存 |
Private Clean | 只屬于當前進程但未修改的頁(可能被回收) |
Swapped Dirty | 被換出至 swap 空間的臟頁數(常見于低內存設備) |
Heap Size | Java/Dalvik 堆的總大小 |
Heap Alloc | 已分配的堆內存大小 |
Heap Free | 堆中未分配的剩余空間 |
每一類內存段說明
區域 | 說明 |
---|---|
Native Heap | C/C++ 層分配的堆,常由 malloc 或 native 層庫使用 |
Dalvik Heap | Java 層內存(對象等)使用情況 |
Dalvik Other | 除了對象外的 Dalvik 使用,比如 Class Metadata |
Stack | 每個線程的棧內存(通常為 1MB/線程) |
Ashmem | Android 共享內存機制 |
Gfx dev /GL mtrack | 與圖形相關的內存,比如 UI、OpenGL 緩存等 |
.so mmap | 動態鏈接庫占用的內存 |
.apk/.dex/.ttf mmap | 被 mmap 映射的 APK/Dex/字體文件,不直接進入 Java Heap |
EGL mtrack | EGL 映射軌跡(GPU 分配追蹤) |
Unknown | 未知來源的內存,常用于估算遺漏項 |
App Summary 段解釋
命令輸出后段通常還會出現以下摘要信息:
App SummaryPss(KB)Java Heap: 15234Native Heap: 8488Code: 8352Stack: 96Graphics: 4002Private Other: 1120System: 6789
項目 | 說明 |
---|---|
Java Heap | Java 對象實際占用的堆內存(已分配) |
Native Heap | C 層 malloc 等 native 占用 |
Code | .so /.dex /.apk mmap 映射的只讀代碼部分 |
Stack | 線程的棧空間 |
Graphics | 圖形緩沖區使用,如 Skia / SurfaceFlinger |
Private Other | 無法明確歸類的私有內存段 |
System | 系統級別共享內存,如 binder、ashmem、zygote 映射等 |
實戰用法與技巧
- 快速定位內存占用高的進程
adb shell dumpsys meminfo | grep "TOTAL"
輸出每個進程的總內存占用,對比誰最占內存。
- 結合
top
使用,確認是否導致內存抖動
adb shell top -n 1 -m 10
adb shell dumpsys meminfo <package_name>
查看是否 Java Heap 或 Native Heap 正在持續上升。
- 導出分析數據備份
adb shell dumpsys meminfo com.example.app > meminfo.txt
保存為本地文本,配合 Git 歷史記錄查看趨勢。
注意事項
dumpsys meminfo
的數值僅代表瞬時快照,并非持續記錄- App 必須處于運行中,否則不會顯示完整信息
- 不支持系統服務(如
system_server
)的詳細堆棧分布 - 若需要 GC 后的堆大小,建議先使用:
adb shell am send-trim-memory <package_name> TRIM_MEMORY_COMPLETE
推薦組合命令
adb shell dumpsys meminfo com.example.app > meminfo.txt
adb shell am dumpheap com.example.app /data/local/tmp/app.hprof
adb pull /data/local/tmp/app.hprof ./app.hprof
3. adb shell top
(實時監控)
新增參數組合建議:
# 每2秒刷新一次,按內存排序
adb shell top -o RES -m 5 -d 2
參數 | 作用 |
---|---|
-o | 排序字段(RES=內存,%CPU=CPU) |
-d | 刷新間隔(秒) |
-m | 顯示最大進程數 |
4. adb shell setprop libc.debug.malloc
(Native內存追蹤)
作用:啟用Bionic庫的malloc調試功能,記錄Native代碼的內存分配堆棧(需root權限或調試版ROM)
關鍵參數說明:
參數值 | 作用 |
---|---|
backtrace | 記錄每次分配的堆棧(默認16幀,可通過backtrace=32 調整) |
log | 輸出分配日志到/data/tombstones/malloc_debug_* |
program=<name> | 僅追蹤指定進程(如app_process ) |
options="backtrace,guard" | 組合選項(guard=啟用內存邊界檢查) |
典型使用流程:
# 1. 啟用追蹤(需root或adb root)
adb shell stop
adb shell setprop libc.debug.malloc.program com.example.app
adb shell setprop libc.debug.malloc.options backtrace=32
adb shell start# 2. 復現問題后導出日志
adb pull /data/tombstones/malloc_debug_* ./# 3. 使用addr2line解析堆棧(需對應so庫的調試符號)
arm-linux-androideabi-addr2line -e libnative.so 0x1234 0x5678
輸出示例:
# malloc_debug_12345.txt 內容片段
@ 0xb6f04567 [com.example.app+0x123456]/project/jni/utils.cpp:42 malloc(1024)
@ 0xb6f089ab [com.example.app+0x789abc]/project/jni/image_processor.cpp:89 new ImageBuffer()
5. adb shell am send-trim-memory
(內存壓力測試)
作用:模擬Android系統在不同內存壓力下的回收行為,驗證應用的內存管理策略
完整等級表:
等級參數 | 系統行為 | 典型觸發場景 |
---|---|---|
TRIM_MEMORY_UI_HIDDEN | 通知Activity進入后臺 | 用戶按Home鍵 |
TRIM_MEMORY_RUNNING_MODERATE | 釋放可緩存資源 | 系統剩余內存<50% |
TRIM_MEMORY_RUNNING_LOW | 停止后臺服務 | 系統剩余內存<30% |
TRIM_MEMORY_RUNNING_CRITICAL | 準備被殺死 | 系統剩余內存<15% |
TRIM_MEMORY_COMPLETE | 強制釋放所有非關鍵資源 | 系統內存嚴重不足 |
自動化測試腳本示例:
# 模擬內存壓力升級過程
for level in UI_HIDDEN RUNNING_MODERATE RUNNING_LOW COMPLETE; doadb shell am send-trim-memory com.example.app TRIM_MEMORY_$levelsleep 3adb shell dumpsys meminfo com.example.app | grep "TOTAL PSS"
done
以下是補充 adb shell am dumpheap
命令后的完整內容,在保留原有 dumpsys meminfo
相關說明的基礎上,新增 dumpheap
的詳細說明:
6. adb shell am dumpheap(堆內存導出到文件)
1. 命令作用
am dumpheap
是 Android 的 Activity Manager (am) 工具提供的命令,用于將指定進程的 堆內存(Heap) 導出到文件,供后續分析(如檢測內存泄漏、對象分配情況等)。導出的文件是標準的 HPROF 格式,可用 Android Studio、MAT(Memory Analyzer Tool)等工具分析。
2. 命令語法
adb shell am dumpheap <pid|process_name> <file_path>
<pid|process_name>
:目標進程的 PID 或包名(如com.example.app
)。<file_path>
:堆轉儲文件的保存路徑(需設備有寫入權限)。
3. 使用示例
示例 1:通過包名導出堆內存
adb shell am dumpheap com.example.app /data/local/tmp/heap.hprof
示例 2:通過 PID 導出堆內存
adb shell ps -A | grep com.example.app # 先查找 PID
adb shell am dumpheap 1234 /sdcard/heap.hprof
示例 3:導出系統進程的堆內存(需 root)
adb shell su -c "am dumpheap system_server /data/local/tmp/system_heap.hprof"
4. 關鍵注意事項
-
文件路徑權限:
- 默認情況下,普通應用無權寫入 /data/local/tmp 之外的系統目錄。
- 建議導出到 /sdcard/(需設備有存儲權限)或通過 run-as 寫入應用私有目錄:
-
adb shell run-as com.example.app am dumpheap com.example.app /data/data/com.example.app/heap.hprof
-
進程凍結:
- 執行
dumpheap
時,目標進程會被短暫凍結(STW,Stop-The-World),可能導致界面卡頓或 ANR(尤其在主線程轉儲時)。
- 執行
-
文件拉取:
-
導出的
.hprof
文件需通過adb pull
復制到本地分析:adb pull /sdcard/heap.hprof ./
-
-
HPROF 轉換:
-
Android 的 HPROF 是 Dalvik 格式,部分工具(如 MAT)需轉換為標準 Java HPROF:
hprof-conv /path/to/android.hprof /path/to/java.hprof
(
hprof-conv
工具位于 Android SDK 的platform-tools
目錄)
-
5. 實際應用場景
- 內存泄漏分析:結合 MAT 或 Android Studio Profiler 檢查對象引用鏈。
- OOM 調試:在崩潰前主動轉儲堆內存,分析大對象分配。
- 性能優化:對比不同操作前后的堆狀態,定位內存增長點。
6. 高級用法
-
觸發 GC 后轉儲(減少噪聲):
adb shell am dumpheap -g <pid> <file_path>
(
-g
參數會在轉儲前觸發 GC,但部分設備可能不支持) -
自動化腳本:
adb shell am dumpheap $(pidof com.example.app) /sdcard/heap_$(date +%s).hprof
dumpsys meminfo
與 dumpheap
的區別
維度 | dumpsys meminfo | am dumpheap |
---|---|---|
數據類型 | 實時內存統計(PSS/RSS/堆大小等) | 完整的堆內存快照(對象引用關系) |
用途 | 快速查看內存占用概況 | 深度分析內存泄漏或對象分配細節 |
性能影響 | 幾乎無影響 | 短暫凍結進程 |
輸出格式 | 文本 | 二進制 HPROF 文件 |
完整工作流程示例
-
通過
dumpsys meminfo
發現內存異常:adb shell dumpsys meminfo com.example.app
觀察到
Dalvik Heap
或Private Dirty
持續增長。 -
導出堆內存:
adb shell am dumpheap com.example.app /sdcard/suspicious_heap.hprof adb pull /sdcard/suspicious_heap.hprof ./
-
分析 HPROF 文件:
- 使用 Android Studio 的 Memory Profiler 導入文件。
- 或通過 MAT 查找 Leak Suspects(內存泄漏嫌疑對象)。
通過結合 dumpsys meminfo
和 am dumpheap
,可以快速定位內存問題的宏觀表現(如總占用過高)和微觀細節(如具體泄漏對象)。
三、新增分析流程圖
四、實戰技巧補充
- 批量監控腳本:
while true; doadb shell dumpsys meminfo com.example.app | grep "TOTAL PSS"sleep 5
done
- 內存泄漏黃金組合命令
# 1. 觸發GC后立即dump堆
adb shell am dumpheap -g com.example.app /data/local/tmp/app.hprof# 2. 同步時間戳便于關聯日志
adb shell date +%s > ./dump_time.txt# 3. 拉取文件并啟動MAT分析
adb pull /data/local/tmp/app.hprof ./ && memory-analyzer.sh app.hprof
- Native內存分析進階:
# 需要root權限
adb shell stop
adb shell setprop libc.debug.malloc.program app_process
adb shell setprop libc.debug.malloc.options backtrace=32
adb shell start
- MAT快捷分析:
- 使用
Leak Suspects
報告快速定位問題 - 按
Retained Heap
排序查看大對象
- Android Studio Profiler聯動:
# 生成profiler可讀的快照
adb shell am profile start com.example.app /data/local/tmp/app.alloc
adb shell am profile stop com.example.app
五、版本差異與兼容性
Android版本 | Native追蹤支持 | Trim Memory等級 | 關鍵內存指標 |
---|---|---|---|
5.0-6.0 | 需手動編譯libc | 僅前4個等級 | 無Swap統計 |
7.0-8.1 | 內置malloc_debug | 新增BACKGROUND | 引入SwapDirty |
9.0+ | 支持program過濾 | 新增MODERATE | 獨立Graphics分類 |
12.0+ | 優化backtrace性能 | 新增CACHED_RECENT | 不可達對象統計 |
六、附錄:常用工具鏈
- MAT (Memory Analyzer Tool) :分析.hprof文件
- Android Studio Profiler:實時內存可視化
- Perfetto:系統級內存追蹤
- HeapTrack:Linux/Android通用堆分析工具
- Glibc Malloc Debug:NDK開發時使用