
一、问题的本质为什么已占用的内存可以算作空闲在回答为什么previous层级占用的内存可以算在freeRam内之前需要先厘清一个关键概念Android系统中的freeRam并非Linux内核意义上的MemFree。Linux内核中/proc/meminfo的MemFree字段代表物理上完全未被任何对象使用的内存页面。而Android的freeRam是一个逻辑可用内存概念——它的定义是当前可供分配、或在内存压力下可被快速回收的内存总量。这一概念在dumpsys meminfo的输出中有明确体现Free RAM cached pss MemFree即内核空闲页 其他可回收内存。因此previous层级的内存虽然在物理上被占用但在语义上被系统视为可回收候选从而计入freeRam。下面从源码层面逐层剖析这一机制。1.1 进程优先级层级体系ProcessList中的ADJ定义Android在ProcessList.java中定义了完整的进程优先级层级体系每个层级对应一个adj值adj值越大表示进程越不重要越容易被LMK在内存压力下回收UNKNOWN_ADJ 1001 最低优先级缓存进程上限 PREVIOUS_APP_ADJ 700 用户上一个使用的应用 HOME_APP_ADJ 600 Home桌面进程 SERVICE_ADJ 500 包含Service的进程 HEAVY_WEIGHT_APP_ADJ 400 后台重量级进程 BACKUP_APP_ADJ 300 备份进程 PERCEPTIBLE_APP_ADJ 200 可感知进程 VISIBLE_APP_ADJ 100 可见进程 FOREGROUND_APP_ADJ 0 前台进程1.2 previous层级的特殊性介于活跃与可回收之间previous层级之所以特殊在于它处于内存管理语义的边界状态它不是前台进程用户已离开不再有可见的UI交互从用户体验角度可以安全地回收其内存而不会造成直观的体验损失但它也不是普通缓存进程用户可能随时通过最近任务或简单的返回操作切换回来因此系统倾向于优先保留它LRU列表中的头部位置。正是这种可以回收但优先保留的双重属性使得previous进程的内存在统计上被纳入freeRam在管理策略上却享有高于其他缓存进程的保护。二、内存统计模型AMS如何计算freeRam2.1 统计架构MemInfoReader dumpsys meminfoAndroid系统的内存统计通过MemInfoReader类从/proc/meminfo中读取底层数据再结合AMS管理的进程信息进行汇总计算。dumpsys meminfo命令的输出结构清晰地展示了这个统计模型Total RAM: 物理内存总量 Free RAM: 可用内存 缓存进程内存 内核空闲页 其他可回收内存 Used RAM: 已用内存 应用实际使用量(PSS) 内核占用其中Free RAM的计算公式可以近似表达为Free_RAM MemFree CachedPage Cache Cached_PSS缓存进程的PSS总和previous进程的内存被归入Cached_PSS部分从而计入Free RAM。2.2 computeOomAdjLocked进程定级与previous识别的关键逻辑在ActivityManagerService.java中computeOomAdjLocked方法是决定进程所属层级和adj值的核心入口。相关源码逻辑可抽象如下// 位于 ActivityManagerService.java 的 computeOomAdjLocked 方法中 if (app mPreviousProcess app.activities.size() 0) { if (adj ProcessList.PREVIOUS_APP_ADJ) { // 该进程是用户上一个显示UI的进程赋予PREVIOUS_APP_ADJ adj ProcessList.PREVIOUS_APP_ADJ; schedGroup ProcessList.SCHED_GROUP_BACKGROUND; } }上述逻辑表明mPreviousProcessAMS维护的一个引用指向用户最近一次交互的进程。当用户切换到新应用时旧应用进程被记录为mPreviousProcess判据app mPreviousProcess app.activities.size() 0——只有确实包含Activity的进程才被识别为previousadj赋值被识别为previous的进程其adj会被设置为PREVIOUS_APP_ADJ700归类为高优先级的缓存进程。2.3 updateOomAdjLocked将previous纳入缓存进程统计在updateOomAdjLocked或相关统计方法中系统遍历所有进程并按其adj值分类统计。previous进程在统计视角下被归入缓存进程类别其PSSProportional Set Size比例内存占用被计入cached pss进而被纳入Free RAM的计算中。这意味着在系统的统计口径中previous进程的内存既是已使用的物理上被进程占用又是可用的逻辑上可被LMK快速回收后重新分配。2.4 ProcessRecord.curAdj与进程分类的关联每个Java进程在AMS中都有一个对应的ProcessRecord对象其成员变量curAdj记录了该进程当前的优先级。previous进程的curAdj PREVIOUS_APP_ADJ700在以下场合发挥作用统计分类curAdj决定该进程在dumpsys meminfo输出中被归入哪一类LMK回收决策curAdj值越大在内存压力下越优先被LMK选中回收freeRam计算分类为缓存进程后其内存被计入Free RAM的cached部分。三、可回收性为什么previous内存可以算作可用3.1 内核视角Page Cache的可回收属性从Linux内核的角度内存页面大致分为三类页面类型说明可回收性Free pages未被使用的物理RAM立即可分配Cached pages文件支持的页面代码、mmap文件等可快速回收脏页需写回Anonymous pages堆、栈等非文件支持的页面不可直接回收需swap/zRAMAndroid使用的核心原则是free memory is wasted memory空闲内存就是浪费。系统尽量将所有RAM用于缓存最近使用的应用和数据而不是让其空闲。previous进程的内存以Cached pages为主应用的代码映射、资源文件等这些页面可以被内核的kswapd机制快速回收——如果是clean cached pages可以直接丢弃如果是dirty pages需要先写回存储或压缩到zRAM。这种可快速回收的特性是previous内存被纳入freeRam统计的内核层面基础。3.2 LMK回收机制与previous的回收时机Android的Low Memory KillerLMK机制根据adj值决定进程的回收顺序。在ProcessList中不同adj层级被映射到对应的minFree阈值内存下限当系统可用内存低于某个闸值时该层级及更高adj的进程将被回收。previous进程的adj为700属于缓存进程层级。当内存压力达到回收缓存进程的阈值时previous进程虽然位于LRU列表头部比其他缓存进程更晚被回收但依然在可被回收的范畴内。3.3 内存的快速回收属性 vs 物理空闲属性这是理解整个机制的最关键区别物理空闲内存页面上没有任何数据可以立即分配给新请求者。对应内核MemFree。逻辑可用内存页面虽然被占用但承载的数据可以通过丢弃或迁移被快速释放从而变为物理空闲。对应Android的Free RAM概念。previous进程的内存属于后者——它在物理上是used但在语义上是available。当系统需要内存时LMK可以杀掉该进程内核回收其页面内存即可重新分配。整个过程的耗时在毫秒级别对用户体验的影响远小于触发OOM。四、Android 16的演进变化2025-20264.1 内存管理策略的延续与增强Android 16在内存管理方面的演进体现在优化而非重构。根据2025-2026年的开发资料Android 16延续了free memory is wasted memory的核心理念并进行了以下增强更高效的垃圾回收机制优化了ART运行时的GC策略减少了应用在后台时的内存压力动态内存分配策略引入了更细粒度的内存分配控制使系统能更精确地平衡各层级进程的内存占用后台任务调度增强改进了后台进程的约束机制减少不必要的后台内存消费。4.2 previous层级在Android 16中的意义在Android 16中previous层级的重要性不仅没有减弱反而因为多任务场景的日益丰富而更加关键快速切换体验用户频繁在2-3个应用间切换的场景越来越普遍保留previous进程在内存中能显著减少冷启动的延迟和功耗LRU列表头部保护previous进程被置于缓存LRU列表的头部位置这是连接活跃进程和缓存进程的关键过渡层级freeRam统计的合理性将previous内存计入freeRam使系统报告的内存状态更准确地反映了在必要时可以释放的内存而非当前完全空闲的内存这对应用层的内存压力判断如onTrimMemory回调至关重要。五、总结5.1 核心原理总结previous层级占用的内存可以算在freeRam内本质原因在于Android的freeRam定义的不是物理空闲内存而是逻辑可回收内存。这一设计建立在四层基础之上层面关键机制作用语义层Free RAM ≠ MemFree而是包含可回收的cached pages定义统计口径框架层AMS通过computeOomAdjLocked识别previous进程设置curAdjPREVIOUS_APP_ADJ进程定级分类统计层previous进程的内存被计入cached pss纳入Free RAM计算内存统计汇总内核层Page cache的快速回收特性 LMK的adj回收机制保证可回收性5.2 设计哲学Android的这种设计体现了一个深刻的内存管理哲学空闲内存是浪费但随时可释放的缓存内存是财富。系统通过将previous层级的内存统计为freeRam引导应用层和用户正确理解内存状态——这些内存虽然在用但随时可以被释放以满足新的内存需求。这种逻辑空闲视角使Android能够在有限的内存资源下同时实现高效的多任务体验和灵活的内存压力应对。5.3 关键要点回顾previous层级对应PREVIOUS_APP_ADJ 700是用户上一个使用的应用处于活跃进程与缓存进程的过渡边界freeRam的构成包括内核的Free pages、Page Cache的Cached pages以及AMS管理的缓存进程内存含previous进程可回收性是关键previous进程的内存以文件映射页面为主可被内核快速回收这是其被纳入freeRam统计的内核基础AMS的核心方法computeOomAdjLocked负责将用户上一个进程识别为previous并赋予相应的adj值使其在统计口径上被归类为可回收缓存LMK的回收策略保证了在内存压力下previous进程虽然享有LRU头部保护但在必要时仍可被回收从而兑现freeRam统计中的可用承诺。