Android ADB命令之内存统计与分析
一、核心命令总览
工具 / 命令 | 用途 | 示例 |
---|---|---|
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开发时使用