什么是ANR?
ANR(Application Not Responding),即应用程序无响应,它会严重影响用户体验。
ANR触发条件
ANR本质是一个性能问题,即主线程中的耗时操作造成主线程堵塞,导致应用失去响应能力。
用户触摸操作InputEvent:5s内无响应触发ANR提示;
广播Broadcast:前台广播10s和后台广播60s会触发ANR;
服务Service:前台进程Service20s和后台进程Service200s会触发ANR;
而Service和Broadcast只会打印trace信息,不会提示用户ANR弹窗,大部分可感知的ANR都是由于InputEvent引起的。
Android中ANR的监控机制
Android应用程序是通过消息来驱动的,Android某种意义上也可以说成是一个以消息驱动的系统,UI、事件和生命周期都和消息处理机制息息相关。Android的ANR监测方案也是一样,大部分就是利用了Android的消息机制。
InputEvent的ANR与上图有些不同,是在Native监控,但同样会堵塞主线程的消息队列。
Android中ANR的检测方案
一般来说有四种,分别为BlockCanay、ANR-WatchDog、SafeLooper和FileObserver。
1.BlockCanary
BlockCanary一种非侵入式的轻量性能监控组件,原理巧妙的利用了Android原生Looper.loop中的一个log打印逻辑
这个log打印逻辑正是在Message消息分发前后,监控这两个逻辑之间的时间差就可以得到当前主线程的卡顿状态,如果超时则获取trace信息并上报,具体实现:
这个方案的优缺点如下:
- 优点:灵活配置的可监控常见APP应用性能也可以作为一部分场景的ANR检测,并且可以准确定位ANR和耗时调用栈。
- 缺点
1.Google已经明确标注了这个logger对象是可以被更改的,可能会导致logger为null导致BlockCanary失效;
2.如果dispatchMessage执行的非常久是无法触发BlockCanary的逻辑的;
3.Google在Looper中还有一个标注,那就是queue.next()是可能block的,但是BlockCanary同样无妨适用的;因为inputEvent在queue.next中block,不会继续执行dispatchMessage,而是从native回调给;InputEventReceiver.dispatchInputEvent处理分发,所以BlockCanary也就无法监控到这类ANR;
4.无法监控CPU资源紧张造成的系统卡顿,无法响应的ANR;
ANR-WatchDog
它的思路是开辟一个单独现场向主线程发送一个变量+1操作,自我休眠自定义ANR的阈值,休眠过后判断变量是否+1完成,如果未完成则警告。
- 优点
1.兼容性好,各个机型版本通用;
2.无需修改App逻辑代码,非侵入式;
3.逻辑简单,性能影响不大 -
缺点
无法保证能捕捉所有ANR,对阈值的设置直接影响捕获概率,如图所示:
如果对线程的堵塞大于10s则设置监控阈值5s能捕捉所有ANR,堵塞时间在5s~10s,则可能出现无法捕捉场景
SafeLooper
它主要是通过反射接管主线程Looper的功能,可以自由定制,但是进行message管理会有很大的性能损耗。
FileObserver
Android手机发生ANR后,会把信息存储在/data/anr/traces.txt文件,我们只需要监听这个文件的变化就可以知道是否发生了ANR。
- 优点:
1.基于原生接口调用,时机和内容准确;
2.无性能问题实现简单; - 缺点:
它最大的问题是兼容性问题,5.0之后无法监听了。