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_watchdog | system_server_crash或tombstone |
| 崩溃类型 | 总是 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.so、libandroid_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 崩溃处理的区别
| 特性 | 普通 App | System Server |
|---|---|---|
| FC 对话框 | 弹出"已停止运行" | 不弹框(系统进程无 UI) |
| 进程影响 | 仅该 App 被杀 | 整个系统服务重启 |
| 崩溃后 | 用户可重新打开 App | Zygote 自动重新 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 terminated6.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 PROCESS | FATAL EXCEPTION IN SYSTEM PROCESS |
| DropBox tag | system_server_watchdog | system_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) → 排查驱动八、总结
System Server 崩溃有四种形态:Java 异常、Native crash、OOM/LMK、Watchdog 自杀。
KillApplicationHandler 是所有 Java 崩溃的统一入口,System Server 与普通 App 共用但处理不同(不弹 FC 框)。
Zygote runSelectLoop + init onrestart = 自动恢复机制:System Server 死亡后 Zygote 退出 → init 重新拉起 → 系统热重启。
RescueParty 防止 Boot Loop:多次启动失败后逐级执行恢复策略,最终可能触发恢复出厂设置。
日志产物区分 Watchdog vs Crash:
system_server_watchdogvssystem_server_crash。
下一篇将进入应用层异常——ANR 机制全解。
本文基于 AOSP 7(Android Nougat)源码编写。
