一、崩溃的捕获

1、Java catchException

2、native崩溃,编译是上传符号文件到服务器,获取dump日志后分析

3、anr异常,使用 FileObserver 监听 /data/anr/traces.txt 的变化,高版本不支持,可以用微信Hardcoder,

二、常见的引起anr的原因

1、主线程耗时

2、多线程争抢资源造成死锁

3、所以如果我们使用SharedPreference的apply方法, 虽然该方法可以很快返回, 并在其它线程里将键值对写入到文件系统, 但是当Activity的onPause/onStop等方法被调用时,会等待写入到文件系统的任务完成,如果写入比较慢,主线程就会出现ANR问题。

另外,SharedPreference除了提供apply外还提供commit方法,该方法直接在调用线程中执行,不会转入后台,但如果我们在UI线程commit,且磁盘写入较慢的情况下,ANR依然会发生,这个时候就需要将修改SharedPreference值的任务放到单独线程里去做。

使用SharedPreference时无论使用apply还是commit都会有很小的概率由于写入磁盘问题(IO瓶颈)出现ANR。除了IO瓶颈外,锁瓶颈也是SharedPreference的一个缺点,单个共享数据的文件在被同时操作时会有加解锁开销。

三、崩溃的防治

1、可以用AOP,把特定的方法全部替换成自己的方法,防止崩溃

这类问题的解决原理大致相同,我们以Intent Extras为例详细介绍一下。读取Intent Extras的问题在于我们非常常用的方法 Intent#getStringExtra 在代码逻辑出错或者恶意攻击的情况下可能会抛出ClassNotFoundException异常,而我们平时在写代码时又不太可能给所有调用都加上try-catch语句,于是一个更安全的Intent工具类应运而生,理论上只要所有人都使用这个工具类来访问Intent Extras参数就可以防止此类型的Crash。但是面对庞大的旧代码仓库和诸多的业务部门,修改现有代码需要极大成本,还有更多的外部依赖SDK基本不可能使用我们自己的工具类,此时就需要AOP大展身手了。

2、依赖检查

对不一致的版本和依赖进行上报

3、页面跳转通过路由分发,catch找不到类的错误

4、网络层处理脏数据

5、资源重复检查,我们写了一个Gradle插件通过hook MergeResource这个Task,拿到所有library和主库的资源文件,如果检查到重复则会中断编译过程,输出重复的资源名及对应的library name,同时避免有些资源因为样式等原因确实需要覆盖