当前位置: 首页 > news >正文

Android 7系统异常问题排查(五)Framework层(下)—System Server崩溃

系列目录:第一篇:异常机制全景图 | 第二篇:Kernel Panic 与系统重启 | 第三篇:Tombstone 机制 | 第四篇:System Server Watchdog | 第五篇:System Server 崩溃 | 第六篇:ANR 机制 | 第七篇:Java 层崩溃 | 第八篇:Trace 机制 | 第九篇:日志系统 | 第十篇:实战方法论


一、System Server 崩溃 vs Watchdog 超时

在上一篇文章中我们探讨了 Watchdog 触发的"自杀"——系统卡死 → Watchdog 检测到 → 主动killProcess。本篇分析另一种形态:System Server 因自身异常直接崩溃

维度Watchdog 超时直接崩溃
触发方式Watchdog 主动自杀未捕获异常或 Native 信号
前置症状系统逐渐卡死可能无明显前兆
日志特征system_server_watchdogsystem_server_crashtombstone
崩溃类型总是 Java 层自杀Java 异常 / Native crash / OOM

二、崩溃类型分类

2.1 Java 层未捕获异常

System Server 是 Java 进程,其中任何线程抛出的未捕获异常都会导致进程崩溃:

常见 Java 崩溃类型: ├─ NullPointerException — 空指针 ├─ ArrayIndexOutOfBounds — 数组越界 ├─ IllegalStateException — 非法状态 ├─ ClassCastException — 类型转换错误 └─ SecurityException — 权限问题

2.2 Native 层崩溃

System Server 通过 JNI 调用了大量 Native 代码(libandroid_servers.solibandroid_runtime.so等),Native 层崩溃同样会生成 tombstone。

2.3 OOM / LMK 杀掉

当系统内存极度紧张时,LMK(Low Memory Killer)可能会杀死 System Server。虽然 System Server 的oom_score_adj被设为较低值(-800 左右),但在极端情况下仍可能被选中。

2.4 Watchdog 触发的自杀

严格来说这也属于崩溃的一种,但我们已经在上篇文章中详细分析过。


三、崩溃处理链路源码分析

3.1 System Server 的 UncaughtExceptionHandler

System Server 进程同样使用RuntimeInit.KillApplicationHandler作为默认的未捕获异常处理器:

源码路径frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

publicclassRuntimeInit{// ...privatestaticIBindermApplicationObject;privatestaticvolatilebooleanmCrashing=false;privatestaticfinalvoidcommonInit(){// 设置默认的未捕获异常处理器Thread.setDefaultUncaughtExceptionHandler(newKillApplicationHandler());}privatestaticclassKillApplicationHandlerimplementsThread.UncaughtExceptionHandler{publicvoiduncaughtException(Threadt,Throwablee){try{// 防止递归崩溃if(mCrashing)return;mCrashing=true;// 1. 确保异常信息被记录到 logcatensureLogging(t,e);// 2. 尝试通过 AMS 记录崩溃信息if(mApplicationObject==null){Slog.e(TAG,"Attempted to log uncaught exception "+"with null mApplicationObject.");}else{IActivityManageram=ActivityManagerNative.asInterface(mApplicationObject);am.handleApplicationCrash(mApplicationObject,newApplicationErrorReport.CrashInfo(e));}}catch(Throwablet2){// 连 AMS 都联系不上时直接记录日志Slog.e(TAG,"Error reporting uncaught exception",t2);}finally{// 3. 终止进程Process.killProcess(Process.myPid());System.exit(10);}}}}

关键设计ensureLogging()确保异常堆栈被写入 logcat,即使 AMS 调用失败也能从日志中看到崩溃信息。mCrashing标志防止递归崩溃(handler 自身异常时不会再次调用)。

3.2 System Server 与普通 App 崩溃处理的区别

特性普通 AppSystem Server
FC 对话框弹出"已停止运行"不弹框(系统进程无 UI)
进程影响仅该 App 被杀整个系统服务重启
崩溃后用户可重新打开 AppZygote 自动重新 fork
crashCount限制连续崩溃后不再弹框N/A

3.3 AMS.handleApplicationCrash() 的处理

当 System Server 自身调用AMS.handleApplicationCrash()时,实际上 System Server 自己就是 AMS 的宿主——这相当于"自己通知自己即将崩溃"。

源码路径frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

publicclassActivityManagerServiceextendsActivityManagerNativeimplementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback{// ...@OverridepublicvoidhandleApplicationCrash(IBinderapp,ApplicationErrorReport.CrashInfocrashInfo){ProcessRecordr=findAppProcess(app,"Crash");finalStringprocessName=app==null?"system_server":r==null?"unknown":r.processName;// 1. 添加 DropBox 条目addErrorToDropBox("system_server".equals(processName)?"system_server_crash":"crash",r,processName,null,null,null,null,null,crashInfo);// 2. 崩溃日志输出到 logcatSlog.e(TAG,"*** FATAL EXCEPTION IN SYSTEM PROCESS: "+processName);// 3. 如果进程还存在,尝试收集线程堆栈if(app!=null&&r!=null){// dump stack traces// ...}}}

关键设计:System Server 崩溃时 DropBox tag 是system_server_crash,而普通 App 是data_app_crash——这决定了后续日志分析时的过滤关键字。


四、Zygote 重启机制

4.1 Zygote 如何检测 System Server 死亡?

Zygote 进程在 fork System Server 之后,会进入runSelectLoop()等待子进程退出:

源码路径frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

publicclassZygoteInit{// ...publicstaticvoidmain(Stringargv[]){try{// ... 初始化 ...if(startSystemServer){pid=Zygote.forkSystemServer(...);if(pid==0){// 子进程:启动 System ServerhandleSystemServerProcess(parsedArgs);return;}}// 父进程(Zygote):进入主循环runSelectLoop(abiList);// ...}catch(MethodAndArgsCallercaller){caller.run();}}privatestaticvoidrunSelectLoop(StringabiList)throwsMethodAndArgsCaller{// ...while(true){// 使用 select/poll 等待子进程退出或新连接// 当 system_server 退出时,Zygote 会检测到并退出}}}

关键设计:Zygote 通过runSelectLoop()中的select()系统调用监听子进程状态。当 system_server 退出时,Zygote 会检测到 SIGCHLD 信号并退出自身进程。

4.2 init 进程的编排作用

源码路径system/core/rootdir/init.zygote32_64.rc

service zygote /system/bin/app_process32 -Xzygote /system/bin \ --zygote --start-system-server --socket-name=zygote class main socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver onrestart restart media onrestart restart netd service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin \ --zygote --socket-name=zygote_secondary class main onrestart restart zygote

注意onrestart配置的是重启 Zygote 依赖的 native 服务(audioserver、cameraserver 等),而非 system_server。当 Zygote 退出时,init 会根据onrestart配置重新拉起 Zygote,新 Zygote 启动时会通过--start-system-server参数自动重新 fork system_server。

4.3 完整重启链路

System Server 崩溃 ↓ Zygote 检测到子进程退出(通过 runSelectLoop 中的 select) ↓ Zygote 自身退出 ↓ init 进程检测到 Zygote 退出(SIGCHLD) ↓ init 根据 init.zygote*.rc 中 onrestart 配置: ├─ restart audioserver/cameraserver/media/netd └─ 重新拉起 Zygote(因为 service 配置了 class main) ↓ 新 Zygote 启动 → fork 出新的 System Server ↓ System Server 重新初始化所有服务(AMS/WMS/PMS...) ↓ 用户感知:屏幕短暂黑屏/卡顿后恢复("热重启")

五、Boot Loop 机制保护

5.1 问题场景

如果 System Server 在启动阶段就崩溃,Zygote 会不断重启,形成Boot Loop(反复重启循环),设备永远无法进入正常使用状态。

5.2 RescueParty(AOSP 7 引入)

AOSP 7 引入了RescueParty机制来应对 Boot Loop:

源码路径frameworks/base/services/core/java/com/android/server/RescueParty.java

publicclassRescueParty{// ...publicstaticvoidnoteBoot(Contextcontext){// 系统启动成功后调用// 重置重启计数}publicstaticvoidnoteSystemServerRestart(Contextcontext){// System Server 每次重启时调用// 如果在短时间内重启次数过多 → 进入救援模式if(getRestartCount()>THRESHOLD){executeRescueLevel(context,nextLevel());}}privatestaticvoidexecuteRescueLevel(Contextcontext,intlevel){switch(level){caseLEVEL_RESET_SETTINGS:// 1. 重置系统设置到出厂值resetGlobalSettings(context);break;caseLEVEL_RESET_TRUSTED_DEFAULTS:// 2. 恢复可信任的默认配置resetTrustedDefaults(context);break;caseLEVEL_FACTORY_RESET:// 3. 恢复出厂设置RecoverySystem.rebootWipeUserData(context,...);break;}}}

关键设计:RescueParty 通过持久化存储记录 System Server 重启次数。如果短时间内重启超过阈值,会逐级执行恢复策略:重置设置 → 恢复默认 → 恢复出厂。

Rescue Level 递进

频繁重启 Level 1 → 重置系统设置 仍然重启 Level 2 → 恢复可信任默认值 仍然重启 Level 3 → 提示用户恢复出厂设置

六、日志产物分析

6.1 logcat 中的关键日志

// Java 层崩溃 AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: main AndroidRuntime: java.lang.NullPointerException: ... AndroidRuntime: at com.android.server.am.ActivityManagerService.xxx(AMS.java:1234) // Native 层崩溃 libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 1234 (system_server) // Zygote 重启 Zygote: Process 1234 exited due to signal 11 Zygote: Exit zygote because system server (1234) has terminated

6.2 DropBox 条目

dumpsys dropbox system_server_crash--print

输出包含完整的 Java 异常堆栈:

Tag: system_server_crash Process: system_server Flags: 0x28... Package: android Subject: system_server ... java.lang.NullPointerException at com.android.server.am.ActivityManagerService.xxx(AMS.java:1234) at ...

6.3 tombstone(Native Crash 时)

如果 System Server 是 Native 层崩溃,/data/tombstones/中也会有墓碑文件,按第三篇的方法还原即可。


七、定位方法论

区分 Watchdog 自杀 vs 直接崩溃

判断依据Watchdog 自杀直接崩溃
logcat 关键字WATCHDOG KILLING SYSTEM PROCESSFATAL EXCEPTION IN SYSTEM PROCESS
DropBox tagsystem_server_watchdogsystem_server_crash
堆栈特征线程多处于 Blocked/Waiting明确抛出java.lang.XXX异常
tombstone一般没有Native crash 时有

定位步骤

1. 确认崩溃类型 → logcat 搜索 "FATAL EXCEPTION IN SYSTEM PROCESS" → 或 "Fatal signal" (Native crash) 2. 提取异常信息 → dumpsys dropbox system_server_crash --print → 或 /data/tombstones/tombstone_XX (Native crash) 3. 分析异常堆栈 → Java crash: 直接看异常类名 + 堆栈行号 → Native crash: ndk-stack 还原 4. 回溯崩溃前日志 → logcat -b all -d | grep -B 50 "FATAL EXCEPTION" → 寻找崩溃前的异常操作或错误日志 5. 确定根因 → 代码逻辑错误 → 修改代码 → 资源问题(OOM) → 优化内存 → 驱动问题(Native crash) → 排查驱动

八、总结

  1. System Server 崩溃有四种形态:Java 异常、Native crash、OOM/LMK、Watchdog 自杀。

  2. KillApplicationHandler 是所有 Java 崩溃的统一入口,System Server 与普通 App 共用但处理不同(不弹 FC 框)。

  3. Zygote runSelectLoop + init onrestart = 自动恢复机制:System Server 死亡后 Zygote 退出 → init 重新拉起 → 系统热重启。

  4. RescueParty 防止 Boot Loop:多次启动失败后逐级执行恢复策略,最终可能触发恢复出厂设置。

  5. 日志产物区分 Watchdog vs Crashsystem_server_watchdogvssystem_server_crash

下一篇将进入应用层异常——ANR 机制全解。


本文基于 AOSP 7(Android Nougat)源码编写

http://www.jsqmd.com/news/1333047/

相关文章:

  • 微信公众号爬虫终极指南:5步获取文章阅读点赞数据的完整方案
  • Memory Barrier
  • AI率90%以上还有救吗?实测95.7%降到3.7%,重灾区能降下来。
  • C# Socket编程从入门到实战:解决粘包、高并发与工业通讯
  • 2026年7月安徽省亳州市电信融合宽带套餐避坑全攻略 - 领卡园地
  • Redis开机自启失败:systemd服务管理与配置问题深度排查指南
  • Windows 10系统封装与母盘制作:从虚拟机优化到Sysprep部署实战
  • Oracle表空间扩展实战:DBA必备的三种扩容方案与避坑指南
  • AiToEarn:AI 内容创作与变现一站式平台
  • Windows 11资源管理器仿macOS访达:深度UI定制与美化实战
  • stm32f103 舵机 机械臂+视觉抓取(原理超级简单!)
  • 手机上的宝可梦存档编辑器:PKHeX.Mobile完全使用指南
  • CentOS 8静态IP配置详解:从原理到实战的完整指南
  • MerchantOps-KBQA 实践(一):基于 FastAPI、Milvus 的商户运营知识库问答系统
  • 在macOS上无缝运行Windows应用:Whisky的轻量级解决方案
  • 如何用Postman便携版实现零安装API测试:完整免费教程
  • 2026年7月安徽省池州市联通融合宽带一篇说透 - 领卡园地
  • 2026微信商城搭建有哪些平台?适配不同商家场景的工具参考
  • 万万没想到 LM358 也能采集心电
  • 内容安全三道防线:内容审核API的多场景接入与响应解读
  • Obsidian Encrypt 深度解析:全面掌握笔记加密安全技术 [特殊字符]
  • Windows C盘空间不足?安全高效清理与优化全攻略
  • 智慧灌溉是什么,为什么节水增效里离不开它
  • UEDumper:自动化逆向分析虚幻引擎内存布局的实战指南
  • systemd服务启动报错Permission denied:从文件权限到SELinux的完整排查指南
  • 如何用TEdit泰拉瑞亚地图编辑器打造你的专属像素世界
  • 魔兽世界高层秘境实战复盘:DKT红玉23.8万秒伤与进度机制解析
  • AI Agent学习:Harness工程——模型之外的Agent核心竞争力(李博杰《深入理解 AI Agent》1.2观后总结)
  • Unity3D集成阿里云小云KWS模型实现游戏本地语音控制全链路实践
  • Mac百度网盘提速终极指南:3种免费加速方案让下载速度提升70倍