Skip to main content

Chapter 65: Background Process Reclamation

后台进程回收讨论的是一个用户经常遇到、但很难直接看到的系统动作:用户离开一个 App 后,系统把它留在内存中以便快速返回;当内存、功耗、温度或前台响应受到压力时,系统又会终止这个后台执行容器,把资源转给当前更高优先级的任务。本章要让读者能够追踪一次后台回收从用户切换 App 到进程消失、再到重新恢复界面的完整路径。

本章的贯穿材料是一款笔记 App。用户正在编辑草稿,按 Home 或手势切到相机拍照,又打开地图导航,最后从最近任务列表返回笔记。返回时可能出现三种结果:界面立即恢复、界面重新创建但草稿仍在、界面重新创建且草稿丢失。三种结果的差异来自同一条系统路径:App 进入后台后,进程重要性降低;系统在资源压力下选择回收;App 下次入口承担状态恢复和数据一致性责任。

后台回收的核心结论是:手机系统把进程视为可回收资源,把用户任务视为需要恢复的状态。进程存活能提升返回速度,但进程存活消耗内存、可能保留后台执行机会,也会影响前台任务的响应。系统因此按前台可见性、后台任务语义、资源压力和平台策略给进程排序,在必要时回收低优先级进程。

本章使用公开材料建立边界:Android 的进程重要性和 cached process 行为以 Android Processes and app lifecycle 为基础,Android 低内存回收执行层以 AOSP Low memory killer daemon 为公开依据;Apple 侧只使用 UIKit App lifecyclebackground executionUIBackgroundModes 和 MetricKit 这类公开入口描述可观察行为,Jetsam 优先级和具体选择细节属于平台内部策略,正文按公开行为和合理架构推断处理。

65.1 Background Reclamation 的系统动机

Background Reclamation 指系统在 App 退到后台后,根据资源压力和进程重要性终止进程、回收内存并收缩后台执行机会的策略集合。它解决的主问题是手机资源总量有限,而用户当前感知集中在前台界面、音频、导航、通话、输入和通知等少数任务上。系统要把有限内存、CPU 时间、I/O 带宽、电池预算和散热空间优先分配给这些任务。

在笔记 App 例子中,用户切到相机后,笔记界面已经不可见。系统仍可能把笔记进程保留在内存中,因为保留进程能让用户返回时跳过进程创建、代码加载、对象初始化和部分数据读取。这个保留动作是性能优化:进程还在,页面对象、缓存和运行时堆仍在,返回路径可以更短。

同一个保留动作也带来资源成本。笔记进程持有 Java/Kotlin 或 Swift/Objective-C 对象、native heap、图片缓存、数据库连接、文件映射、线程栈和图形资源引用。部分 file-backed 页面可以被内核丢弃后重新读取,匿名堆和脏页则需要真实内存或交换空间承载。当前台相机需要大块图像缓冲区、地图需要瓦片缓存和定位服务、系统 UI 需要保持触控响应时,后台笔记进程就从“返回加速缓存”变成“可回收资源”。

后台回收还服务功耗和热控制。后台进程即使处于不活跃状态,也可能通过定时器、网络回调、数据库同步、线程池或 framework callback 获得执行机会。系统把后台执行收束到 Job、Work、foreground service、background task、push、后台定位、音频等可识别入口,是为了让平台知道这段工作是否仍然和用户意图相关。可识别的后台任务可以被调度、延后、合并或降级;脱离系统入口的线程在进程降级后缺少保护。

下面的图把贯穿材料中的一次切换放入系统路径。图的边界是 App 进程到系统策略层,省略具体驱动和硬件寄存器,突出“进程保留”和“进程回收”在同一条路径中的分支。

图中最关键的判断点是资源压力和进程重要性的组合。系统回收后台进程时,目标并非关闭用户任务,而是释放执行容器。用户任务能否继续,取决于 App 是否把草稿、导航位置、未提交操作和界面恢复入口保存到进程外。

65.2 Memory Pressure 与进程回收优先级

Memory Pressure 是系统内存分配、页面回收、交换、文件缓存收缩和任务阻塞共同呈现出来的压力状态。手机系统判断内存压力时,关注点不止是空闲内存数量,还包括分配延迟、页面回收成本、前台线程是否被内存短缺拖慢、缓存是否频繁失效和系统是否开始抖动。Android 在公开文档中说明,较新的 lmkd 可以使用 Pressure Stall Information 监测任务因内存不足而等待的时间;这个指标直接关联用户体验,因为等待会推迟前台绘制、输入处理和服务响应。

进程回收优先级由两个信息源合成。第一个信息源是进程对当前用户体验的贡献:前台界面、可见界面、正在执行的 receiver、foreground service、bound service、普通 service、cached activity、empty process。第二个信息源是进程自身占用的资源和最近使用价值:驻留内存大小、脏页比例、是否持有可重建缓存、最近是否被用户使用、是否服务于输入法、桌面、系统 UI、正在播放音频或导航定位。系统以这些信息构造“先回收谁”的顺序。

Android 的公开进程层级把 foreground process、visible process、service process 和 cached process 放入不同重要性等级。foreground process 支撑用户当前操作,visible process 支撑用户仍能看到或意识到的内容,service process 承载用户可能关心但界面不可见的工作,cached process 当前没有活动组件需要运行。系统在资源不足时优先选择 cached process;服务进程和可见进程在更高压力下才进入候选范围。

Apple 平台公开暴露的是 active、inactive、background、suspended 等生命周期状态,以及后台执行、后台模式和诊断报告。应用进入 suspended 后通常不执行用户代码,但进程内存仍可能保留。内存压力升高时,系统可以终止 suspended app,把内存转给前台 App 和系统服务。具体 Jetsam priority、阈值和排序属于内部策略,开发者能依赖的是状态恢复契约和诊断信号,而非某个固定阈值。

进程优先级也受依赖关系影响。Android 文档明确说明,如果进程 A 绑定了进程 B 的 service,或正在使用进程 B 的 content provider,进程 B 的分类会至少达到和 A 相当的重要程度。这个规则说明回收顺序并非单个进程孤立排序。系统要保护调用链上的服务端进程,否则前台客户端会因为后台服务端被回收而立即失败。

在笔记 App 中,草稿页面退到后台后通常进入 cached 或 suspended 语义。如果它正在通过系统认可的上传任务同步附件,或正在播放录音,进程重要性可能被提升。若它只是持有一个后台线程继续保存草稿,线程本身不会自动向系统声明用户重要性。资源压力上升时,系统可终止进程,线程随进程一起消失。这个例子给出一个可迁移判断顺序:先看用户可见性,再看系统认可的后台任务入口,再看依赖关系,最后看内存压力和平台排序。

65.3 Android Cached Process 回收策略

Android 的 cached process 是当前没有活动组件需要运行、可以在资源需要时被系统终止的进程。Android 官方文档把它定义为系统可按需要杀死的进程,并说明 cached process 里常保留已经执行 onStop() 的 Activity。进程被系统终止时,onDestroy() 没有调用保证;应用返回时应通过 Activity 生命周期保存的状态和持久化数据恢复界面。

Android 的策略链可以拆成五层。App 层的 Activity、Service、BroadcastReceiver、ContentProvider 决定当前组件是否活跃。Framework 层由 ActivityTaskManager、ActivityManager 和相关服务维护任务栈、组件状态、进程记录和重要性。内核接口层通过 oom_score_adj、memory cgroup、PSI 或 vmpressure 等信息表达候选对象和压力信号。用户空间 lmkd 监听压力并选择目标进程。进程终止后,AMS 观察死亡、清理记录,并在用户重新进入时触发新的进程创建和组件重建。

这条路径中,lmkd 承担的是回收执行动作,进程语义主要来自 framework。lmkd 不理解笔记草稿的业务含义,它只依据系统交给它的进程重要性、压力信号和设备配置执行回收。业务状态能否保住,由 App 在更高层完成:草稿保存到数据库、文件或 DataStore,导航状态保存到可恢复参数,网络 mutation 进入可重试队列。

Android 的 empty process 和 cached process 都可能承担“下次启动加速”的缓存角色。empty process 没有活动组件,保留它通常是为了重用进程环境;cached process 可能包含 stopped Activity 的对象图和运行时状态。系统保留它们能降低 warm start 或 resume latency,但这些进程没有强生命周期承诺。Android 文档还标注,从 Android 13 开始,cached process 在进入 active lifecycle state 之前可能获得很少甚至没有执行时间。这个版本边界影响后台线程设计:处于 cached 状态的进程应把执行机会视为稀缺资源。

Foreground service 是 Android 给用户可感知长期工作的显式入口。播放媒体、导航、通话、健康追踪、正在上传的用户任务等场景可以通过 foreground service 提升进程重要性,并伴随通知让用户看到它仍在运行。这个提升不是永久护身符。系统和平台版本会限制 foreground service 类型、启动时机、通知要求和后台启动资格;进程在严重内存压力下仍可能失败,任务需要持久化进度和可恢复设计。

在笔记 App 中,普通编辑页面退到后台后应按 cached process 处理。草稿保存动作适合在用户输入后增量提交到本地持久化层,长时间上传附件适合交给 WorkManager、JobScheduler 或 foreground service 这类系统可识别入口。把保存逻辑放在后台线程里等待几分钟后执行,会把关键数据和 cached process 的存活绑定在一起,进程回收后用户就会看到草稿丢失。

65.4 Apple Suspended App 与 Jetsam 回收路径

Apple 平台的公开生命周期把 App 前台、后台和 suspended 状态分开。App 退到后台后,系统通常给它一个短执行窗口完成收尾;窗口结束后,普通 App 会进入 suspended 状态。Suspended app 仍可能驻留内存,但不运行应用代码。这个状态和 Android cached process 在工程含义上相近:系统把它当成返回加速资源,在内存压力下可以回收。

Jetsam 是 Apple 平台中常用来描述内存压力下终止进程的公开诊断术语。对开发者而言,关键可观察结果包括:App 没有收到普通前台退出路径中的完整回调;下次打开时表现为新进程启动或 scene 重新连接;诊断报告可能标记内存相关终止原因。具体 Jetsam 优先级、阈值和实时排序由系统内部决定,公开资料不足以把它写成稳定 API 契约。

Apple 的回收路径可以用责任边界描述。UIKit 或 SwiftUI 管理 scene、window、application lifecycle callback。系统 daemon 和内核内存管理共同感知内存压力、前台任务需求和后台执行资格。内核与平台策略选择 suspended 或低优先级后台进程作为回收对象。开发者可控制的部分集中在状态保存、后台任务注册、内存告警响应、缓存清理和下次启动恢复。

在笔记 App 中,用户切出后,应用可能收到 scene 进入 background 的回调,并获得有限时间保存状态。进入 suspended 后,计时器、普通网络回调和应用线程不应被当成可靠执行路径。若相机和地图造成内存压力,系统可终止笔记进程。用户从最近任务返回时,系统可能重新启动 App,并通过 scene session、restoration activity、deep link 或普通启动入口恢复界面。

Apple 后台例外由公开能力声明和系统批准共同控制。音频播放、位置更新、蓝牙外设、外部附件、VoIP push、后台 URLSession、BGTaskScheduler 等场景都有各自入口、约束和用户可见语义。它们表达的是“这类工作在后台仍有用户价值”,并把执行权交给系统调度。它们不表达“整个 App 进程应长期自由运行”。

开发者在 Apple 平台上排查后台回收,应把证据分成三类。第一类是公开 lifecycle callback 和 scene 状态,说明 App 何时进入后台或恢复。第二类是系统诊断,例如 crash report、MetricKit diagnostic、Jetsam 相关日志条目,说明终止是否和内存有关。第三类是应用自己的持久化记录,例如草稿更新时间、未完成 mutation 队列和恢复入口参数,说明进程死亡后业务状态是否完整。

65.5 后台任务、音频、定位、网络与例外保留

后台例外保留解决的是“用户离开界面后,某项工作仍然代表当前用户意图”的问题。系统需要给这类工作一定执行机会,同时保持可调度、可审计和可收缩。例外保留的共同特征是:App 通过公开 API 或配置声明任务类型;系统服务或 daemon 掌握任务所有权;用户通常能通过通知、状态栏、权限面板、定位指示器、音频控件或系统设置感知这项后台活动。

场景Android 常见入口Apple 常见入口系统关注点回收边界
长期音频MediaSession、foreground service、音频焦点audio background mode、AVAudioSession用户能听到内容,路由和中断需由系统协调音频任务受保护,缓存和无关页面仍可清理
导航定位foreground service、location API、权限和通知location background mode、Core Location位置访问敏感,功耗高,需用户授权和指示定位链路可延续,UI 对象仍需可重建
蓝牙通信Bluetooth API、foreground service 或系统任务bluetooth-central / bluetooth-peripheral mode外设连接需低功耗调度和权限控制连接事件可唤醒,进程状态仍受系统控制
大文件传输WorkManager、JobScheduler、DownloadManager、foreground servicebackground URLSession网络、电量和数据策略决定执行时机传输归系统调度,进度需持久化
Push 触发FCM / platform push、JobAPNs、background push、PushKit 限定场景系统控制唤醒频率和可执行时间Push 提供入口,长期执行需另有资格

表中的差异说明,例外保留保护的是任务语义,不是整个进程的全部内存。一个导航 App 后台导航时,定位和音频提示可能保持运行,但历史页面的大图片缓存、无关列表页和预加载数据仍然应可清理。一个笔记 App 上传附件时,上传任务可以交给系统调度,编辑页面对象无需常驻。

后台网络尤其容易被误解。用户点击上传附件后切出 App,这个用户意图仍然存在,但普通线程执行上传会跟随进程回收一起消失。Android 应把可延后、需约束条件的后台工作放入 WorkManager 或 JobScheduler;需要立即且用户可见的长期工作才考虑 foreground service。Apple 应使用 background URLSession 或 BGTaskScheduler 等系统入口,让传输和调度由平台托管。这样即使进程被回收,任务状态也能在系统或持久化层中延续。

音频和定位的保护强度高于普通后台同步,因为用户可感知和硬件占用都更明确。音频占用输出路由,定位占用 GNSS、Wi-Fi、蜂窝和传感器组合,蓝牙占用外设连接状态。系统允许这些任务后台运行,同时通过权限、指示器、通知、后台模式声明和系统设置暴露给用户。任务滥用会受到平台限制、审核规则、权限撤销和系统调度收缩。

对笔记 App 来说,最稳定的策略是把后台工作拆成两层。第一层是必须立即保住的本地用户状态,例如草稿文本、附件引用、光标附近上下文和编辑时间戳,应在前台输入路径中增量保存。第二层是可以延后的远端同步,例如上传附件、同步全文索引和发送协作事件,应通过系统认可的后台任务入口提交。这样后台回收最多改变同步完成时间,不会改变用户草稿是否存在。

65.6 Process Death 对用户状态和数据一致性的影响

Process Death 影响的是执行容器,不直接表达用户任务结束。用户从最近任务返回笔记 App 时,心理模型是“继续刚才的草稿”;系统模型可能是“启动一个新进程,并把它导航到一个可恢复任务”。这两个模型之间的落差由 App 架构填平。App 需要把 UI state、navigation state、domain state、persistent state 分层保存。

UI state 是当前界面临时形态,例如输入框内容、选中 tab、滚动位置、光标位置、弹窗展开状态。它变化频繁,适合在生命周期边界和关键输入后保存到轻量 state holder 或持久化快照。Navigation state 是用户处在什么任务中,例如正在编辑哪篇笔记、从哪个列表进入、是否处于附件选择流程。它应能转换为 route、document id、scene activity 或 deep link 参数。

Domain state 是业务事实,例如草稿正文、附件元数据、协作者版本、已提交操作和冲突状态。它应保存在数据库、文件、远端或本地事务日志中。Persistent state 是进程外长期可依赖的事实集合,包括本地数据库、文件系统、key-value store、上传队列和幂等请求记录。后台回收后能恢复用户任务,依赖的是 domain state 和 persistent state,而非内存中的对象图。

数据一致性风险通常来自 pending mutation。用户在笔记中输入三段文字,App 把它们存在内存队列,准备 10 秒后批量写入数据库。进程在这 10 秒内被回收,三段文字就消失。更稳定的做法是把输入合并策略放在持久化层附近:前台输入先写入本地草稿表或日志表,再用延迟任务做压缩、同步或上传。这样批处理失败影响网络同步效率,不影响本地事实。

另一个风险来自缓存和事实混淆。图片缩略图、搜索索引、列表分页缓存可以在进程回收后重建;草稿正文、附件选择、用户确认过的删除操作和付款类 mutation 需要持久化事务。App 如果把“可重建缓存”和“用户事实”都放在同一组内存对象里,回收后就难以判断哪些内容可以丢弃,哪些内容必须恢复。

恢复路径应按可复用顺序设计。第一步,根据启动入口判断用户意图:普通图标启动、最近任务返回、通知点击、分享入口或 deep link。第二步,读取持久化任务状态:正在编辑的文档、未完成上传、草稿版本和本地事务。第三步,重建 navigation 和 UI state:打开对应页面、恢复光标和滚动位置,并标记需要刷新远端数据。第四步,恢复后台任务:检查队列、重试幂等请求、处理冲突。这个顺序把进程死亡纳入正常输入,而非异常尾部处理。

65.7 后台回收作为手机系统功耗与内存策略的一部分

后台回收属于手机系统的全局资源策略,和内存、功耗、温度、网络、传感器以及前台体验共同决策。内存压力是最直接触发因素,但回收效果会扩展到 CPU 调度、I/O 竞争和能耗曲线。终止低价值后台进程后,系统减少页表、堆、缓存、线程和回调机会,前台 App 更容易获得连续 CPU 时间和稳定内存分配。

功耗策略影响后台进程的执行窗口。手机电池预算有限,系统倾向于把后台网络、同步、定位和计算合并到少量窗口执行,减少唤醒次数、无线模块切换和 CPU 频率波动。Android 的 Job、Work、foreground service 限制和 cached execution 收缩,Apple 的 background task、background URLSession、background modes 和 suspended state,都体现了同一方向:后台工作要进入系统可调度入口。

温控策略会进一步压缩后台空间。相机、游戏、导航和视频通话会同时使用 CPU、GPU、ISP、display、modem、speaker、GNSS 或 NPU,热压力上升时,系统需要保护前台帧率、输入响应、拍摄链路和通话稳定。后台进程在这种环境下继续占用内存和执行机会,会放大前台体验波动。回收低优先级进程可以降低系统压力,使降频和任务收缩更可控。

后台公平性也是回收策略的一部分。若某个 App 退到后台后仍长期保留大量内存和执行机会,它会压缩其他 App 的返回速度和前台空间。移动平台通过进程重要性、后台模式、权限、通知、调度窗口和审核规则,把后台资源变成受系统分配的公共资源。用户当前任务、明确授权和可见提示构成后台资源的主要资格。

把本章路径迁移到其他现象时,可以使用同一组问题。这个 App 当前是否可见?它是否有系统认可的后台任务?这项任务是否有用户可见结果?它持有的内存中哪些是可重建缓存,哪些是用户事实?回收后入口如何恢复?这组问题能把“后台被杀”“草稿丢失”“上传中断”“返回变慢”放回同一套系统路径中解释。

本章最终建立的理解是:后台回收不是平台随机关闭 App,而是手机系统在前台体验、内存水位、电池预算、热限制和后台公平性之间执行的资源再分配。App 架构的正确目标是让进程可被回收,让用户任务可恢复,让后台工作进入系统可调度边界。

最小自检任务

用户在笔记 App 中输入一段草稿,随后切到相机拍照,又打开地图导航。十分钟后用户从最近任务返回笔记 App,发现 App 重新显示启动页,草稿有时存在,有时丢失。请按本章模型写出这次现象的系统路径、Android 与 Apple 的共同边界、可能的后台例外、以及 App 侧应检查的状态保存点。

答案要点

系统路径应从用户切出 App 开始:笔记界面不可见,进程从前台或可见状态降级到 cached 或 suspended 语义;相机和地图提高内存、图形缓冲、定位和功耗压力;系统根据进程重要性、最近使用价值、后台任务资格和资源压力选择回收低优先级后台进程;用户返回时,平台重新创建进程或重新连接 scene,App 通过持久化状态恢复草稿。

Android 侧应定位 Activity 进入 onStop() 后的 cached process 语义、组件重要性、foreground service 或 WorkManager / JobScheduler 是否存在、lmkd 在内存压力下按重要性选择进程、onDestroy() 没有可靠调用保证。Apple 侧应定位 scene 进入 background、普通 App 进入 suspended、后台执行窗口结束、内存压力下 Jetsam 可能终止 suspended app、下次启动通过 scene session、restoration activity 或普通入口恢复。Apple 具体 Jetsam 排序属于平台内部策略,不能当作公开稳定契约。

可能的后台例外包括音频、导航定位、蓝牙连接、后台 URLSession、Android foreground service、Android Job/Work、Apple BGTaskScheduler 和 push 触发入口。这些例外保护的是用户可识别的任务语义,并把执行交给系统调度。它们不保证编辑页面对象、图片缓存或内存队列长期驻留。

App 侧应检查四类状态。UI state 包括输入框内容、光标和滚动位置;navigation state 包括正在编辑的文档 id 和入口路径;domain state 包括草稿正文、附件和协作版本;persistent state 包括本地数据库、文件、事务日志和上传队列。草稿丢失通常说明用户事实仍绑定在进程内存或延迟写入队列中。稳定修复路径是前台输入增量持久化,本地事实先落盘,远端同步进入可重试后台任务。

本章知识点总结

  • 回收对象:后台回收释放的是 App 进程这个执行容器,用户任务需要通过进程外状态继续存在。
  • 系统动机:系统回收后台进程是为了把内存、CPU、I/O、电池和热预算转给当前更高优先级任务。
  • 压力判断:内存压力包含空闲内存、页面回收、任务阻塞、缓存抖动和前台响应延迟等信号。
  • 优先级来源:进程回收顺序由用户可见性、组件状态、后台任务资格、依赖关系和资源占用共同决定。
  • Android 路径:Android 通过 framework 维护进程重要性,并由 lmkd 结合内核压力信号执行低内存回收。
  • Cached 语义:Android cached process 可提升返回速度,也可在资源需要时被终止,onDestroy() 没有调用保证。
  • Apple 路径:Apple suspended app 可驻留内存但通常不执行代码,内存压力下可能被 Jetsam 终止。
  • 公开边界:Apple 的生命周期和诊断信号可公开观察,Jetsam 具体排序和阈值属于平台内部策略。
  • 例外保留:音频、定位、蓝牙、网络传输和 push 等后台例外保护任务语义,不保护整个进程的全部内存。
  • 状态分层:UI state、navigation state、domain state 和 persistent state 应分层保存,恢复路径才能跨进程死亡成立。
  • 一致性原则:用户事实应先进入持久化事务或本地日志,远端同步和批处理可以由后台任务延后执行。
  • 架构结论:移动 App 应默认进程可回收、任务可恢复、后台工作可调度,把进程死亡纳入正常系统输入。