在 Android 设备上,内存是一种关键且有限的资源。作为 Android 平台开发者或 OEM,了解从 Java 运行时到 Linux 内核的每个层级的内存工作原理,对于构建高性能且稳定的系统至关重要。
本指南全面概述了 Android 内存架构、可用于分析的工具,并提供了实操练习,帮助您识别和解决与内存相关的问题。
目标
完成本指南后,您将能够:
- 解释 Android 内存的基本概念,包括 Zygote 进程模型和内存映射文件。
- 区分常驻内存大小 (RSS)、按比例分摊的内存大小 (PSS) 和独占内存大小 (USS)。
- 使用
dumpsys meminfo和showmap等标准命令行工具快速评估内存用量。 - 使用 AHAT 捕获和分析 Java 堆转储,以查找泄漏和过度分配。
- 使用 Perfetto 和
heapprofd剖析整个系统的 Java 内存和原生内存。 - 了解系统级内存压力指标,例如压力停滞信息 (PSI),并监控低内存终止守护程序 (LMK) 活动。
- 观察内核级回收活动,包括 ZRAM 交换和页面缓存逐出。
指南结构
本指南分为以下几个部分,旨在按顺序阅读:
- 基本概念:Android 内存的核心技术原理。
- 快速评估工具:使用
meminfo、showmap和procstats进行快速分类。 - 分析 Java 内存:使用 AHAT 深入探究 Java 堆。
- 位图和内存:了解图片对 RAM 的影响,并使用工具对其进行分析。
- 分析原生内存:使用 Perfetto 和
heapprofd分析 C/C++ 内存。 - WebView 和内存:了解 WebView 的多进程架构和内存占用。
- 应用代码即内存:了解类加载和 dex 膨胀对 RAM 的影响。
- 线程和内存:分析原生线程堆栈的开销。
- 内存局部性和性能:了解数据访问模式如何影响 CPU 性能。
- 服务绑定和进程状态:了解跨进程依赖项如何影响 OOM 分数。
- 系统级问题排查:监控 PSI、LMK、ZRAM 交换空间和页面缓存逐出。
- 内存回收:逐出和交换:了解 memcg、charge 和使用
memory.reclaim的主动回收。 - kswapd 和 lmkd 交互:了解 kswapd 和 lmkd 在压力下如何协同工作。
- 将内存页返回给操作系统:使用
madvise和posix_fadvise将未使用的堆页和文件缓存页返回给内核。 - 通过精简进程保持后台工作运行:将后台服务和工作器移至专用进程,这样就不会以较高的优先级保留界面和显存。
前提条件和环境
本指南提供了参考工作流、基准数据和案例研究,演示了如何诊断和解决 Android 内存问题。
- 分析工具:本指南中的方法主要使用标准 Android 性能工具,包括 Perfetto、
dumpsys meminfo、showmap和 AHAT。 - Root 权限:某些系统级诊断工作流(例如检查内核内存压力或硬件 PMU 计数器)需要在 userdebug 设备或模拟器 build 上具有提升的 root 权限 (
adb root)。
起点:基本概念