一、Android内存管理概述:为什么需要低内存杀进程?
大家好,我是你们的讲师。今天咱们聊聊Android内存管理,特别是那个让无数开发者又爱又恨的——低内存杀进程机制。
先问个问题:你手机用着用着,切回微信发现要重新加载,或者游戏打着打着突然退出了。这是为什么?
说白了,就是系统在“抢内存”。Android不像iOS那样有严格的后台管理,它允许应用在后台待着。但内存就那么大,后台应用多了,前台应用就不够用了。这时候,系统就得做出选择——杀掉一些进程,腾出空间。
我刚开始做Android系统开发时,也纳闷过:为什么不能像PC那样用虚拟内存?后来才明白,移动端有移动端的苦衷。
1.1 Android内存压力来源
内存压力从哪来?我把它分成三类:
- 应用层压力:每个App都在抢内存。你装100个应用,每个后台占50MB,那就是5GB。我见过一个社交App,光图片缓存就吃了300MB。
- 系统服务压力:System Server、SurfaceFlinger这些系统进程,它们也得活着。系统服务一旦挂了,手机就重启了。
- 硬件限制:手机不像PC能插内存条。出厂多大就多大,用户没法升级。4GB内存的手机,现在跑个微信+抖音就快满了。
核心观点:Android杀进程不是bug,是feature。它是在有限资源下,保证前台体验的无奈之举。
1.2 为什么不用Linux的OOM Killer?
你可能会问:Linux内核不是有OOM Killer吗?为什么Android还要自己搞一套?
嗯,这里要注意。Linux的OOM Killer是“最后手段”,它是在内存彻底耗尽时才触发。而且它杀进程的方式很粗暴——谁占内存多杀谁。
但Android不一样。它需要更精细的控制:
- 前台应用优先级最高,不能随便杀
- 后台服务可以杀,但得按优先级来
- 缓存进程可以优先杀,因为它们随时能重启
我曾在项目中遇到过一个问题:某个视频App在后台播放音乐,结果被OOM Killer干掉了。用户投诉说“听着歌突然断了”。这就是因为OOM Killer不懂Android的优先级。
所以Android搞了一套自己的机制——Low Memory Killer(LMK),后来演变成了现在的LMKD。它根据进程的“重要性”来决定杀谁,而不是单纯看内存占用。
1.3 内存压力的分类与等级
Android把内存压力分成了几个等级,就像台风预警一样:
| 压力等级 | 触发条件 | 系统行为 |
|---|---|---|
| 轻度 | 可用内存低于阈值1 | 开始回收缓存页、压缩内存 |
| 中度 | 可用内存低于阈值2 | 开始杀缓存进程、后台服务 |
| 重度 | 可用内存低于阈值3 | 开始杀前台服务、甚至部分可见进程 |
| 临界 | 内存几乎耗尽 | 触发内核OOM Killer,可能杀任何进程 |
这些阈值不是固定的。不同厂商、不同机型会调优。我记得有一次帮客户调试,发现某款手机在内存还剩800MB时就开始杀进程了。用户觉得“明明还有内存,为什么卡?”其实是因为厂商把阈值设得太保守了。
避坑指南:我曾经调试过一个案例,App在后台频繁被杀死。后来发现是因为App申请了太多匿名共享内存(ashmem),导致系统误判为内存压力大。解决方案是限制App的ashmem使用量。
1.4 杀进程的代价
杀进程不是免费的。每次杀进程都有代价:
- 用户体验代价:App重启、数据丢失、加载变慢
- 性能代价:重新创建进程、加载资源,CPU和IO开销
- 电量代价:频繁杀进程和重启,反而更耗电
所以Android在杀进程这件事上,一直在做权衡。杀得太狠,用户骂;杀得太松,系统卡。
我个人习惯是:在系统调优时,先观察一段时间的kswapd和lmkd日志,看看内存压力到底在哪。不要盲目调阈值。
1.5 本章小结
好了,咱们总结一下:
- Android杀进程是因为内存有限,必须保证前台体验
- 它比Linux的OOM Killer更智能,能按优先级杀进程
- 内存压力分等级,系统在不同等级下采取不同措施
- 杀进程有代价,调优时要权衡利弊
下一章,咱们会深入LMK的源码,看看它到底是怎么决定“杀谁”的。你想想看,一个系统要在一毫秒内做出生死判决,是不是挺刺激的?
注意:本章内容基于Android 12+的LMKD机制。不同版本可能有差异,但核心思想一致。