本文要点
- ANR概述
- 发生ANR后Android系统的执行流程
- ANR-WatchDog原理与实战
- ANR的传统解决套路
- ANR模拟实战
- 线上ANR监控方案【ANR-WatchDog原理分析】
- ANR-WatchDog实战
- ANR-WatchDog总结
- ANR-WatchDog与AndroidPerformanceMonitor的区别
项目GitHub
ANR概述
-
KeyDispatchTimeout,5s
即按键或者触摸事件,在特定的时间(一般5s)之内没有响应;
-
BroadcastTimeout,前台10s,后台60s
BroadReceiver 在特定的时间(一般前台10s,后台60s)之内没有响应完成;
-
ServiceTimeout,前台20s,后台200s
Service 在特定的时间(一般前台20s,后台200s)之内没有处理完成;
发生ANR后Android系统的执行流程
- APP发生ANR
- 进程接收异常终止信号,开始写入进程ANR信息(当时场景,包含当前线程所有堆栈信息、CPU/IO的使用情况等);
- 弹出ANR提示框,提示用户关闭APP或者继续等待;(不同ROM表现不同,有的手机厂商会去掉这个提示框)
ANR的传统解决套路
- 【线下】在AS的Terminal中,使用
导出上面提到的adb pull data/anr/traces.txt 要存储在本地的路径
ANR现场信息文件
;
导出来后,便可对文件内容进行详细分析:从
等原因思考;CPU、IO、锁冲突
ANR模拟实战
-
模拟ANR原因:锁冲突;
更改代码:

运行程序,等到程序ANR或崩溃,
在Terminal使用刚刚提到的命令,导出ANR的信息文件:
生成文件:
打开文件,可以找到原因:
上次的BlockCanary同样捕捉到原因:
线下套路其实就是在APP发生ANR时,
导出信息文件,
查看文件,结合代码进行分析;
线上ANR监控方案
- 通过
FileOberver
监控上述的ANR信息文件的变化,
如果这个文件发生了变化,那就说明发生了ANR,
那便可以把它上报到服务器,进行详细的分析;
【高版本需注意权限问题】
- ANR-WatchDog
- 依赖
compile 'com.github.anrwatchdog:anrwatchdog:1.4.0'
- 官网 https://github.com/SalomonBrys/ANR-WatchDog
- 原理(源码分析):
本身就是ANRWatchDog
的子类:Thread
Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别 ANRWatchDog
中,用一个绑定了主线程Looper的Handler,
去处理
_ticker
【一个Runnable任务单元】;
任务单元对一些值进行了处理,如
、_tick
:_reported
Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别
在初始为_tick
ANRWatchDog
的全局变量时,被赋值为0;^^^^^^^^^^^^^^^^^
在
的ANRWatchDog
run()
中,
首先被利用去判定
被post没有(因为一开始就_ticker
为0的话说明_tick
_tick
还没被post),
没有便将
=加上_tick
,之后post了卡顿周期
_ticker
;
此时
不为0!!^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_tick
中的_ticker
,再一次将run()
_tick
置零;^^^^^^^^^^^^^^^^^^^^^^^^^^
所以只要
不被处理,其_ticker
便不会执行,run()
就不会被置零,_tick
由此根据Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别
的值可以判断_tick
是否被处理了;_ticker
重新归零则主线程处理了_tick
,_ticker
不为零则判定_tick
,它没处理主线程卡顿
!!!!!!!!_tick
Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别
的ANRWatchDog
run()
中,
用刚说的主线程Handler,post了
_ticker
这个任务,
然后自己sleep一段时间【即一个卡顿周期,稍后细说】,
如果sleep结束之后,如果
_tick != 0 && !_reported
,
则说明主线程还没有处理
的_ticker
run()
,
没有处理
_ticker
这个任务单元,
那便认为
发生了主线程
卡顿
【如源码注释所示】:!!!!!!
确定发生了卡顿,就开始封装一个
,进行后续处理了:ANRError
另外补充一下,Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别 ANRWatchDog
提供了两个重载的构造器,
提供给开发者对
进行设置,开发者不设置则使用卡顿判定周期
默认配置
:
【跟
同一个德行】BlockCanary
接着仔细看Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别
的构造流程ANRError
这里是有两种构造方式Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别
、New()
NewMainOnly()
,其最终处理都差不多,
就是通过
mainLooper
拿到主线程,
再通过主线程拿到
现场的堆栈信息
,
最后返回构造好的
实例:ANRError
拿到Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别 ANRError
实例之后,
通过
回调机制处理_anrListener.onAppNotResponding(error);
实例;ANRError
Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别 回调机制就妙啊!^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
刚刚的
只是一个应用层上的调用;_anrListener.onAppNotResponding(error);
onAppNotResponding()
的实现方式暴露给开发者了,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
在外部可以通过
自己定制包含不同处理方式的setANRListener()
ANRListener
:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别 开发者不定制,则使用框架自带的默认处理方式呗:
处理方式简单粗暴哈,直接把
ANRError
丢出去,
这样APP就直接
了:崩溃
Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别
乃是ANRError
的子类:Error
Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)ANR概述发生ANR后Android系统的执行流程ANR的传统解决套路ANR模拟实战线上ANR监控方案ANR-WatchDog实战总结与AndroidPerformanceMonitor的区别 - 依赖
ANR-WatchDog实战
- 引入依赖
- 初始化ANR-WatchDog:
-
还是上面那个项目,手动阻塞60s,
运行程序,
程序会5s后崩溃【5s是默认周期时间,崩溃操作见上面源码分析】
在
定位关键字logcat
,可以看到fatal
ANRError
打印的信息,
信息中包括了
的崩溃现场所有线程
堆栈信息
;
以及显示
;bug代码的位置
优化:
当然默认的APP崩溃处理法并不妥当,
影响用户体验,
实际开发中,
我们可以自己定义
ANRListener
,自定义处理方式【上面说过了】,
把堆栈信息上报给服务器就是了!!!!
总结
- 非浸入式
- 弥补高版本无权限问题
与AndroidPerformanceMonitor的区别
-
AndroidPerformanceMonitor:
原理是基于Handler-Message机制,
监控主线程每一个Message的执行,
在每一个Message的分发执行前后,进行信息处理;
(不足:
一般没有阻塞的情况下,
每一个Message的执行时间是非常短暂的,
达不到ANR的级别;
而且InputEvent在queue.next中block,不会继续执行dispatchMessage,
而是从native回调给InputEventReceiver.dispatchInputEvent处理分发,
所以BlockCanary也就无法监控到这类ANR)
-
ANR-WatchDog:
不管主线程是怎么执行的,
只管最后的结果,
我sleep一个周期之后,就要看我
_tick
值有没有被修改,
没被修改就是ANR!
-
适合全程监控卡顿,AndroidPerformanceMonitor
ANR-WatchDog
适合补充ANR监控;
两者可以相辅相成,结合使用!