1、内存管理概述:Android内存管理架构、内存阈值的作用、OOM Killer机制简介

各位同学好,我是老张。今天咱们开始聊Android内存管理。说实话,这个主题我讲了快十年,每次都有新感悟。你想想看,手机卡顿、应用被杀、系统重启——这些问题的根子,十有八九都出在内存管理上。

嗯,咱们先搭个框架。这一节我会把内存管理的整体架构、阈值的作用、还有那个让人又爱又恨的OOM Killer,一次性讲清楚。

1.1 Android内存管理架构

Android的内存管理,说白了就是一套「资源分配与回收」的机制。它不像Linux桌面系统那样,内存不够了就疯狂swap。移动设备没有那么大容量的交换空间,所以策略完全不同。

我习惯把Android内存管理分成三层来看:

  • 内核层(Kernel):负责物理内存的分配与回收。Low Memory Killer(LMK)就住在这里。
  • 系统服务层(System Server):AMS(ActivityManagerService)和WMS(WindowManagerService)在这里干活。它们决定「哪个进程该杀」。
  • 应用框架层(Framework):提供ActivityManager、ProcessList等API给上层应用调用。

这三层的关系,我画个简图你感受一下:

应用层 (App)
    ↓ 调用
框架层 (AMS, ProcessList)
    ↓ 决策
系统服务层 (System Server)
    ↓ 执行
内核层 (LMK / OOM Killer)
    ↓ 回收
物理内存

我在项目中遇到过一个问题:某款手机在后台播放音乐时,突然被杀了。查了半天,发现是AMS在计算进程优先级时,把音乐进程的adj值算高了。这就是架构层之间配合出了问题。

1.2 内存阈值的作用

内存阈值,你可以理解为「水位线」。就像水库有警戒水位一样,Android系统也设了好几道线。

为什么要设阈值?直接原因就一个:防止系统彻底卡死。你想想看,如果内存被吃光了,连启动一个「杀进程」的线程都没空间了,那手机就真的死透了。

Android里常见的阈值有这些:

阈值名称 含义 典型值(4GB设备)
minfree 各等级进程保留的最小空闲页数 12288, 15360, 18432, 21504
adj 进程优先级,值越大越容易被杀 0~1000
cache_min 缓存进程的最小数量 8~16
extra_free_kbytes 额外保留的可用内存 根据总内存动态计算

核心要点:阈值不是越高越好。设得太高,系统频繁杀进程,用户体验差;设得太低,内存耗尽才动手,系统容易卡死。这个平衡点,需要根据设备的内存大小、使用场景来调。

我记得有一次帮客户调优,他们的一款2GB内存的低端机,总是杀后台应用。我一看阈值配置,minfree设得跟4GB设备一样。这明显不合理。调低之后,后台留存率提升了30%。

1.3 OOM Killer机制简介

OOM Killer,全称Out-Of-Memory Killer。名字听着挺吓人,其实它就是个「最后的清道夫」。

它的工作逻辑很简单:当系统内存耗尽,无法再分配新内存时,OOM Killer会选择一个进程杀掉,释放内存

但问题来了——杀谁?

OOM Killer不是随机选的。它有一套评分机制:

// 每个进程都有一个 oom_score_adj 值
// 值越大,越容易被杀
// 前台进程的 adj 值通常为 0
// 后台缓存进程的 adj 值可能高达 900~1000

// 内核计算 oom_score 的简化逻辑:
oom_score = 进程实际内存占用 + oom_score_adj 的加权值

说白了,就是「谁占内存多、谁优先级低,就杀谁」。

这里有个坑,我曾经踩过:某款手机在玩大型游戏时,突然黑屏重启。查log发现,游戏进程自己触发了OOM。为什么?因为游戏申请了一块超大纹理内存,系统来不及回收,直接触发了OOM Killer。而游戏进程的adj值虽然低,但它的内存占用太大了,评分一算,还是它自己中招。

避坑指南:OOM Killer不是bug,它是系统最后的保护机制。但如果你发现系统频繁触发OOM,那说明阈值配置或者内存泄漏有问题。不要试图禁用OOM Killer,那只会让系统死得更难看。

1.4 三者之间的关系

讲到这里,你可能有点晕:LMK、OOM Killer、阈值,它们到底怎么配合的?

我打个比方你就明白了:

  • 内存阈值 = 水库的警戒水位线
  • LMK(Low Memory Killer) = 日常巡逻的保安,水位超过警戒线就开始赶人(杀进程)
  • OOM Killer = 最后的爆破队,大坝快垮了才出手

LMK是「预防性」的,它在内存还够用的时候就提前动手。OOM Killer是「补救性」的,它只在万不得已时才出手。

我个人习惯把LMK看作是第一道防线,OOM Killer是最后一道。调优的时候,优先优化LMK的阈值,让它在内存剩余15%~20%时就开始回收。这样OOM Killer基本不会触发。

小技巧:查看当前设备的LMK阈值,可以用 adb shell cat /sys/module/lowmemorykiller/parameters/minfree。如果看到四个数字,那就是四个等级对应的阈值。单位是「页」,1页=4KB。

好了,这一节的内容就到这里。内存管理架构是基础,阈值是调优的关键,OOM Killer是兜底机制。这三者搞明白了,后面讲具体配置策略时,你就能理解为什么这么设、不这么设会有什么后果。

下一节,咱们会深入分析LMK的源码实现,看看它到底是怎么「杀人」的。嗯,到时候我会带你们手撕一段内核代码。