真实面经题目 · 原创解析
客户端 Crash 发生后如何定位问题?
客户端 Crash 定位要从复现、日志、崩溃栈、符号化、版本环境、用户操作路径和近期变更入手,先判断是 Java/Kotlin 异常、Native 崩溃、ANR、OOM 还是系统兼容问题,再结合监控聚合和最小复现找到根因。
真实面经题目 · 原创解析
客户端 Crash 定位要从复现、日志、崩溃栈、符号化、版本环境、用户操作路径和近期变更入手,先判断是 Java/Kotlin 异常、Native 崩溃、ANR、OOM 还是系统兼容问题,再结合监控聚合和最小复现找到根因。
可以按“收集信息、分类、还原现场、定位根因、修复验证”回答。首先收集 crash 日志、堆栈、设备型号、系统版本、App 版本、线程、用户路径、网络状态和最近发布变更;然后区分 Java/Kotlin exception、Native signal、ANR、OOM、系统 API 兼容或三方 SDK 问题。Java 崩溃重点看 exception 类型和业务栈,Native 崩溃要符号化 so 并看 signal、寄存器和 tombstone,ANR 看主线程阻塞和锁等待,OOM 看内存曲线、对象引用和大图资源。定位时把崩溃聚合、日志面包屑、埋点、灰度版本、git diff 和最小复现结合起来。修复后要补单测或回归用例,灰度观察 crash-free、同栈复发率和相关性能指标。
Crash 定位最怕只有一句“闪退了”。有效现场至少包括崩溃堆栈、线程名、进程名、App 版本、构建号、设备型号、系统版本、前后台状态、页面路径、关键操作、网络状态、账号分群、实验开关和最近日志。移动端问题常具有设备和版本差异,没有这些维度就很难判断是普遍代码缺陷、兼容性问题、灰度配置问题还是个别环境问题。
不同类型的崩溃排查方法不同。Java/Kotlin 异常看异常类型、业务栈和空指针来源;Native 崩溃看 signal、fault address、寄存器、so 版本和符号化结果;ANR 看主线程在做什么、是否等待锁、Binder 或 I/O;OOM 看内存峰值、对象分布、大图资源和缓存;系统兼容问题则要看 API 调用、厂商 ROM 和权限行为。先分类能避免在错误方向上浪费时间。
线上堆栈通常经过混淆或只包含地址,必须还原成可读信息。Android Java/Kotlin 需要匹配对应版本的 mapping 文件,Native 需要使用同版本带符号信息的 so、addr2line、ndk-stack 或 crash 平台符号化。符号文件必须和线上包完全匹配,否则行号和函数名会误导排查。栈还原后要区分直接崩溃点和根因,崩在系统或三方库里也可能是上层传入非法状态。
崩溃聚合平台能告诉我们影响量、版本分布和高频栈,但根因通常要结合近期代码、配置、资源和三方 SDK 变更。可以按版本引入时间、灰度比例、实验开关和设备分布缩小范围。能复现时要建立最小复现路径;不能复现时要增加关键日志、远程开关和防御性监控。对于偶现崩溃,关注线程竞争、生命周期时序、弱网、后台回收和异步回调更有效。
修复 Crash 不能只让本地不崩。要补充针对根因的测试或回归步骤,例如空状态、异常参数、生命周期切换、旋转屏幕、后台恢复、弱网重试和多线程竞争。发布后要灰度观察同一 crash signature 是否下降,是否出现新栈,crash-free user、crash-free session、ANR 率、OOM 率和业务转化是否正常。对于高风险修复,还应准备远程降级或回滚方案。
Java 崩溃通常有异常类型和 Java/Kotlin 调用栈,例如 NullPointerException;Native 崩溃通常表现为 signal、fault address、寄存器和 native 地址,需要 so 符号化。
先确认混淆 mapping 或 native 符号文件是否上传且版本匹配。没有符号时只能结合地址、日志和版本 diff 粗定位,修复效率会明显下降。
从聚合维度找共同点,如设备、系统、页面、版本和操作路径;再补充关键日志和状态快照,重点检查生命周期、异步回调、多线程竞争和弱网时序。
看同一 crash signature 的数量和影响用户是否下降,同时观察 crash-free user、crash-free session、ANR、OOM 和相关业务指标,防止修复引入新问题。