anr 有好几个维度
1: cpu 性能被耗尽
2:死锁
3:慢方法
关于第一点在应用层是无能为力的,这个需要底层的支持,
对于死锁来说也可以从 crashHandler 处获取相应的信息,这个更方便 快捷 准确
Matrix 关于慢方法的统计
1:字节码插装
使用ASM 在编译器 想代码开始的时候插入一个代码开始的消息, 在代码运行结束的时候向方法插入一个执行结束的消息, 这是一种非常巧妙的方法,Matrix 针对性能上的考虑也做到了极致 ,在获取时间上面没有使用 System.currentTimeMillis() 这个方法,既然是计算时间差, 这个方法获取的时间是经过计算的,对于当前的使用场景并没有太大的意义,SystemClock.elapsedRealtime() 通过系统的启动时间即可
2: 使用Looper.logger Matrix 在处理这个logger的时候非常巧妙的先获取了一下 已经被 赋值到 looper 上的 logger, 让自己的logger 持有 这个logger ,那么就会保证在原有logger 不失效的同时,将自身的logger 插入进去, 同时还使用 idelHandler 的原理 来保证自身的logger 即使被替换了,那么也能重新将 logger 添加进去
3:手势 动画等事件的处理可能在上面两个维度都统计不到,就需要借助 Choreographer 或者 OnFrameMetricsAvailableListener 来处理了, 这里面的逻辑 可以去我的另一篇博客 Matrix 原理与技巧总结 fps 篇 看一下,由于时间的关系 代码就先不在这里分析了,
从常理上面来说Matrix 统计的都是慢方法,并没有统计anr 的产生,那么为什么这么做呢,这就和anr产生的原因有关
anr 有几种类型
1 dispatchtouch 类型
2 broadcase 类型
3 service 类型
4 contentprovider 类型
如果主线程卡死了,但是没有上面4种事件,就不会产生anr
就我了解的anr 监控方案还有2个,只不过Matirx 没有选择而已,没有选择的原因是不符合他们的业务逻辑,但并不是这个方法不能使用
1:类似WatchDog(系统重启服务)
性能损耗相对looper.logger来说比较小,自己定时开销肯定会小一些
在线程中执行一个while(true){
-->做一些标识的flag
--> 将这个 消息发送到handler 绑定的messagequeue 的front ,也就是主线程的front,
-->等待 30秒
-->如果 handler 中的消息被执行,那么标识符肯定会被改变
-->检查标识符
}
2:FileObserve
几乎没有性能上的开销
而且可以在其他进程中执行
而且在使用场景上非常适合拥有root 权限的智能设备上面(只有一个app产生track文件,不会收到其他app影响)
原理和使用
在anr 发生的时候,系统会向 data/anr/track_18_08(时间) 写一个文件,使用 FileObserve 监听这个目录,在写完的时候就可以操作这个文件
如果是在C端的情况下,会获取其他app 的anr,但是在智能设备端 ,运行的app不多,大都是自己开发的app,同时还能直接获取到anr 的信息,同时对性能几乎是没有损耗的
同时如果是android 5.0以上的系统,这个事件可能会被 selinux(Linux子安全系统) 拦截,由于root权限后是什么样子我还需要验证一下,