安卓17开始直接杀吃内存的App了
打开手机,切几个应用,突然发现刚才还开着的页面全没了,得重新加载。以前我们都怪系统杀后台太狠。安卓17换了个思路:不再优先收拾那些好好运行的小应用,而是盯上那个一直在偷偷吃内存的家伙,超限就直接把它进程干掉。

谷歌在开发者博客里说得很清楚。设备内存价格往上涨,新机的物理内存容量要么维持原样,要么干脆往下掉,可用户还是要求手机多开流畅。旧机制靠LMK(低内存杀手)在系统整体吃紧时才动手,结果经常是一个有内存泄露的前台服务把整机拖垮,系统只好连带着清掉一堆无辜的后台。用户切回去,全是冷启动,状态丢了,电也跟着多耗。安卓17把这件事提前了。按设备总RAM给每个应用划一条线,先压进zRAM压缩内存,再不行就终止进程。退出原因会写进ApplicationExitInfo,描述里带着MemoryLimiter:AnonSwap。正常优化过的应用几乎感觉不到,真正有问题的那些才会被点名。
以前杀后台为什么总误伤好人
系统内存紧张的时候,LMK会按优先级排队收拾进程。后台缓存的优先,前台服务的往后排。问题就出在这里。有些应用开着前台服务,或者因为泄露一直涨内存,它自己地位高,系统一时半会儿动不了它,只好去杀那些本来安分守己的小应用来腾地方。你再切回去,本来应该热启动的页面变成冷启动,滚动位置没了,游戏进度也丢。CPU还得重新加载,电量跟着多花。
这种连锁反应在低内存设备上更明显。4GB的机器本来就紧张,一个吃内存的家伙一发作,整机体验直接掉档。谷歌现在的目标很明确:别让一个坏演员毁了整台手机的多任务。限制不是固定死的数字,而是跟着设备总内存走。4GB到16GB以上的机型都会陆续用上,先从Pixel开始,后面一年里越来越多厂商会跟进。
我自己测过几款常开的工具类应用,内存曲线看着挺稳,但一碰到图片缓存没清干净的情况,匿名内存就会慢慢爬。以前这种问题最多导致自己卡一下,现在可能直接被系统点名。开发者如果还靠“反正系统会先杀别人”的老思路写代码,后面要倒霉。
超限之后系统会怎么动手
应用占用的匿名内存(堆加上那些没有文件支撑的原生缓冲区)一碰到设备划定的线,系统不会立刻把进程干掉。第一步是强制把页面压进zRAM。压缩和解压都要吃CPU,界面开始掉帧、操作变钝,就是这个阶段。如果应用还继续涨,系统就直接终止它。没有常规的崩溃堆栈,只有ApplicationExitInfo里那一行MemoryLimiter:AnonSwap。
这个设计故意做得保守。谷歌说绝大多数正常会话几乎不受影响,真正针对的是严重泄露和异常占用。开发者可以用TRIGGER_TYPE_ANOMALY触发自动抓堆转储,出问题的时候手里直接有数据。adb也给了调试命令:am memory-limiter status能看当前状态,manual可以临时调某个进程的上限,ignore能让系统暂时放过指定UID。这些命令只对已经启用限制的设备有效。
有人在底下评论说第一批倒霉的可能是Chrome。浏览器这类天生吃内存的应用,缓存策略如果不调整,确实容易撞线。游戏和视频编辑那些本来就需要大内存的,官方表态是正常需求不受影响,只要不是泄露就行。两种做法其实都有人在用:一种是提前把图片和缓存砍到极限,另一种是保留更多数据换流畅度。哪种更合适,得看具体业务。
开发者现在能做的几件事
先把ApplicationExitInfo的监控加上。线上如果出现REASON_OTHER并且描述里有MemoryLimiter,就说明被这套机制点名了。堆转储可以配合ProfilingManager的异常触发自动抓。R8全量模式继续开着,把没用的类和方法干掉,能直接降低字节码占用。LeakCanary现在在Android Studio里集成得更深,本地跑一轮漏检比以前方便。
测试的时候别只盯着自己的旗舰机。用adb把限制调低,或者直接在4GB模拟器上跑长时间场景,看看内存曲线会不会慢慢爬过线。图片加载库如果还在用旧的缓存策略,现在是改的时候了。应用进后台之后主动trim一下不必要的资源,这个老建议在安卓17里权重又高了一截。
我前两天翻了一下自己几个老项目的内存报告,有一个工具类的静态缓存居然一直没释放。以前觉得问题不大,现在得改。改完再压测,匿名内存峰值掉了不少。具体掉多少取决于业务,但方向是对的。
以后再遇到手机莫名其妙卡、后台全被清的情况,先别急着骂系统杀后台。有可能是某个应用在偷偷吃内存,系统已经换了处理方式。开发者这边,把内存基线摸清楚,泄露早点修,比等着被点名再救火划算。
你那边有没有应用最近内存突然涨得很离谱的情况💬
如果你觉得这篇内容对你有启发,欢迎在留言区聊聊你的看法。
关注我,我会持续分享高质量的技术与思考干货。👇