Android开发高手课 - 02 崩溃优化(下):应用崩溃了,你应该如何去分析?

崩溃现场

1. 崩溃信息

  • 进程名、线程名
  • 崩溃类型和堆栈信息

2. 系统信息

  • Logcat
  • 机型、系统、厂商、CPU、ABI、Linux 版本等
  • 设备状态:是否 root、是否模拟器、是否有 Xposed 或多开软件造成

3. 内存信息

  • 系统剩余内存
    通过读取 /proc/memoinfo 获得,MemTotal 表示除了系统本身需要留下可用的总内存,MemFree 表示系统尚未使用的内存
  • 应用使用内存
    包括 Java 内存、RSS、PSS,RSS 和 PSS 可以通过 proc/self/smaps 获取
  • 虚拟内存

4. 资源信息

  • 文件句柄fd
  • 线程数
    线程数量超过400个就比较危险
  • JNI

5. 应用信息

  • 崩溃场景(哪个界面,具体业务)
  • 关键操作路径
  • 其它自定义信息(播放的音乐、打开的网站、运行时间、是否打了补丁等)
  • 磁盘空间、电量、网络使用等

崩溃分析

第一步,确定重点

1. 确认严重程度

2. 崩溃基本信息

  • Java 崩溃,查看错误栈,OOM查看日志中的“内存信息”和“资源信息”
  • Native 崩溃,观察 singal、code、fault addr 等内容,以及崩溃时的 Java 堆栈
  • ANR, 先查看主线程堆栈,是否因为锁等待导致,接着看 ANR 日志确定是 IO 问题、CPU 竞争问题还是大量 GC 导致卡死。

3.Logcat

当从一条崩溃日志中无法看出问题的原因,或者得不到有用信息时,不要放弃,建议查看相同崩溃点下的更多崩溃日志。

4.各个资源情况

内存与线程相关的信息都需要特别注意

第二步,查找共性

机型、系统、ROM、厂商、ABI等等,应用信息也可以作为聚合维度,如打开的链接、播放的视频、国家、地区等

第三步,尝试复现

疑难问题:系统崩溃

1. 查找可能的原因

通过共性归类、操作路径和日志等查找怀疑点

2. 尝试规避

3. Hook 解决

补充

获取 Logcat 的方法

  1. 通过 logcat 命令获取
  2. hook liblog.so 实现
  3. 自定义获取代码

获取 Java 堆栈

  1. Thread.getAllStackTraces();
  2. hook libart.so

课后作业

通过 hook 解决 TimeoutException

问题背景可以参考 这篇文章

  1. TimeoutException 是由系统的 FinalizerWatchdogDaemon 抛出来的,原因是有对象的 finalize 方法的运行时间超过了 10 秒(由 Rom 决定)
  2. 调用 Stop 方法在 Android 6.0 之前存在线程安全问题,是由于调用 thread.interrupt 方法没有加锁
  3. 最终的 hook 方案是把 FinalizerWatchdogDaemon 的 thread 设置为 null,这样 isRunning() 方法就会返回 false,而 runInternal 方法中是一个依赖 isRunning 方法的死循环,所以就 stop 掉了。

猜你喜欢

转载自www.cnblogs.com/fengdianzhang/p/10728525.html