低内存终止守护程序

Android 平台在运行时不会浪费可用的内存。Android 会一直尝试利用所有可用内存。例如,系统会在应用关闭后将其保留在内存中,以便用户快速切回到这些应用。因此,通常情况下,Android 设备在运行时几乎没有未使用的内存(请参阅此处介绍的 Android 内存分配)。

Android 低内存终止守护程序 (LMK) 进程可监控运行中的 Android 系统的内存状态,并通过终止最不必要的进程来应对内存压力较高这一问题,使系统以可接受的水平运行。

为了决定要终止哪个进程,LMK 守护程序使用一个名为 oom_adj_score内存不足得分来确定正在运行的进程的优先级。最高得分的进程最先被终止。后台应用最先被终止,系统进程最后被终止。下表列出了从高到低的 LMK 评分类别。评分最高的类别(即第一行)中的项目将最先被终止:

Android 进程按得分从高到低排序:后台应用、上一个应用、主屏幕应用、服务、可感知应用、前台应用、持久进程、系统进程和原生进程。
图 1. Android 进程,高分在上,低分在下。

内存分析工具

以下工具可以通过以下方式帮助您查找和诊断内存问题:

  • 了解您的应用在一段时间内是如何分配内存的。您可以找到实时图表,了解应用的内存用量、分配的 Java 对象数量以及垃圾回收事件发生的时间。
  • 发起垃圾回收事件,并在应用运行时拍摄 Java 堆的快照。
  • 记录应用的内存分配情况,检查所有分配的对象,并查看每项分配的堆栈轨迹。

如果您的游戏在原生引擎上运行,请使用 HWAddress Sanitizer 调试原生内存分配。

Android Studio 内存分析器

Android Studio 提供 内存分析器 作为 Android Profiler 的一个组件,可帮助您识别可能会导致应用卡顿、冻结甚至崩溃的内存泄漏和内存抖动。分析器会显示一个应用内存使用量的实时图表,让您可以捕获堆转储、强制执行垃圾回收以及跟踪内存分配。

图 2. 在 Android Studio 内存分析器中查看全局 JNI 引用。

Unity 内存分析工具

如果您使用 Unity Engine 构建应用,可以遵循 Unity 内存分析指南。Unity 提供了两种工具来分析 Unity 应用中的内存用量。

第一个是内存分析器模块,这是一个内置的分析器,可提供有关应用在何处使用内存的基本信息。

内存模块显示内存分配情况,例如纹理内存和网格内存。
图 3. 选择了 Memory 模块的 Unity Profiler 窗口。

第二种工具是内存分析器软件包,这是一个可以添加到项目中的 Unity 软件包。该软件包会向 Unity 编辑器添加一个额外的内存分析器窗口。借助内存分析器,您可以更详细地分析应用的内存用量。您可以存储和比较快照,以查找内存泄漏或查看内存布局,从而发现内存碎片问题。

图 4. 使用内存分析器窗口分析内存快照。

Unreal Memory Insights

使用 Unreal Engine 构建的应用可以使用 Unreal Memory Insights 查看有关内存分配和释放的详细信息,包括与内存块关联的低级内存 (LLM) 标记和调用堆栈。

内存分析信息查询系统可以随时查找实时分配,识别内存用量变化,定位内存泄漏,以及区分短期分配和长期分配。

从 UE 5.4 开始,内存分析支持为 Android 项目进行内存跟踪(包含调用堆栈)。

内存分析信息跟踪器,显示主内存图、实时分配计数和分配/释放事件计数。
图 5. Unreal 的内存分析信息跟踪器。

内存不足数据洞见

Android 提供了一些回调和 API,可让您减少游戏的内存需求,并确定之前游戏运行终止的原因。

回调

不注册已废弃的 trim 回调。当系统内存不足时,Android 没有用于检测原生内存压力事件的任何 API。内存整理回调在防止内存不足终止方面效果不佳,因此 Android 弃用了除 TRIM_MEMORY_UI_HIDDENTRIM_MEMORY_BACKGROUND 之外的所有回调

游戏终止

Android 会尝试使用所有可用内存来缓存应用和游戏,以确保它们能够快速加载(从而改善用户体验),但当内存不足时,系统会终止最占用内存的应用和游戏,以释放内存供设备正常运行。

以下信息、数据分析和最佳实践可帮助您更好地利用游戏内存:

  • 使用 ApplicationExitInfo:此 API 会返回 Android 系统终止上一次游戏运行的原因。使用 ApplicationExitInfo 检查低内存是否是导致之前进程运行终止的原因。 检查游戏是否因内存不足而被终止,以便优化游戏,使其在该设备上使用更少的内存。
  • 查看总物理 RAM:为防止游戏在前台运行时被终止,并与设备的功能相匹配,请查看每个设备的总物理 RAM,以便根据该值以精细的粒度调整游戏内存使用量。如果目标是防止应用在移至后台后不久被终止(以允许玩家执行多项任务),请使用 trim 回调(尤其是 TRIM_MEMORY_UI_HIDDEN)来减少游戏内存用量。

其他资源