内存问题排查:从 meminfo 到泄漏定位
2026/8/9大约 4 分钟进程与内存管理Android 14内存排障meminfo泄漏
内存问题排查:从 meminfo 到泄漏定位
前七章把进程与内存机制讲完了。这一章把它们串成排障链:应用被杀、内存暴涨、OOM、 native 泄漏,按什么顺序查、看什么证据。
先用系统水位和 am_kill 判断是系统压力还是目标进程异常,再通过连续 meminfo 样本确认 增长区域。只有确认 Java 堆持续增长后,hprof 才是合适证据;native 增长要走另一套工具链。
先区分系统压力、进程增长与堆上限
| 常见误解 | 正确理解 |
|---|---|
| 内存问题都是 Java 堆泄漏 | native 堆、图片解码、文件映射同样常见 |
| dumpsys meminfo 就是全部证据 | 它给快照,趋势与根因要靠多次采样和 hprof |
| 应用被杀一定是它内存大 | 也可能是优先级低、系统整体紧张或厂商策略 |
核心结论
- 排障顺序固定:系统水位 → 进程占用 → 堆与泄漏 → 杀进程复盘。
dumpsys meminfo看快照,/proc/meminfo看系统水位,多次采样看趋势。- Java 泄漏用 hprof(
am dumpheap)分析;native 用 malloc_debug/procrank 定位。 - 应用被杀先看 am_kill 日志,区分“自己内存大”还是“优先级低”。
- 修复后要复现验证:压测、切后台、重复操作,确认内存不增长。
四层检查链
逐步解释:
- 系统水位:
/proc/meminfo确认是不是系统整体紧张。 - 进程占用:
dumpsys meminfo与多次采样看趋势。 - 泄漏取证:Java 用 hprof,native 用 malloc 工具。
- 杀进程复盘:am_kill 日志确认触发原因与优先级。
常用命令与证据
环境:开发设备或模拟器;部分命令需要 root。
adb shell cat /proc/meminfo
adb shell dumpsys meminfo
adb shell dumpsys meminfo <包名>
adb shell am dumpheap <包名> /data/local/tmp/heap.hprof
adb logcat -v threadtime | grep -E "am_kill|lmkd|OutOfMemory"| 证据 | 含义 | 下一步 |
|---|---|---|
| MemFree/MemAvailable 很低 | 系统水位紧张 | 找占用大户与回收原因 |
| 进程 PSS 持续增长 | 疑似泄漏 | 多次采样,导出 hprof |
| Heap 分配接近上限 | 堆不足 | 分析泄漏或调整内存策略 |
| Native Heap 暴涨 | native 泄漏 | malloc_debug / procrank |
| am_kill 记录 | 被杀原因 | 看 adj 与触发场景 |
常见场景与定位思路
场景一:应用一进后台就被杀
先看 am_kill 日志里的 adj 与原因:是缓存档位过高、系统压力大还是厂商策略。再看进程 内存是否过大。优先级问题与内存问题要用两套证据区分。
场景二:Java OOM
看 dumpsys meminfo 的 Heap 分配与上限,导出 hprof 找泄漏;同时确认 largeHeap 配置。 OOM 多数是堆上限问题,先找“谁占着堆不放”。
场景三:Native 内存暴涨
Native 堆不归 ART GC 管,泄漏更隐蔽。用 malloc_debug 或 procrank 定位分配来源, 关注图片解码、文件映射、JNI 引用等常见泄漏点。
场景四:系统整体卡顿
先看系统水位与 top 内存进程,再查 lmkd 是否频繁杀进程。系统级问题常表现为“反复回收 反复紧张”,根因可能是某个进程的 native 泄漏。
常见误区
- “OOM 就是设备内存不足”:多为进程堆上限问题。
- “只看一次 meminfo 就能定位”:要看趋势与对象级证据。
- “Java 泄漏覆盖一切”:native 泄漏同样常见。
- “被杀就是内存大”:先看 am_kill 里的 adj 与原因。
延伸问题
- procrank、showmap、malloc_debug 分别在什么场景使用?
- hprof 分析泄漏的基本方法是什么?
- 如何用自动化测试稳定复现内存泄漏?
- 厂商低内存策略对应用排查有什么影响?
源码入口
| 文件 | 关键位置 | 作用 |
|---|---|---|
ActivityManagerService.java | 内存统计 | dumpsys meminfo |
OomAdjuster.java | adj 计算 | 优先级依据 |
system/memory/lmkd/ | 杀进程 | am_kill 来源 |
art/runtime/gc/ | 堆管理 | 堆与 OOM |
公共路径沿用本系列各章。行号以 r75 检索为准。
进程状态和优先级的 Framework 来源,回到 AMS 与应用进程。