ANR全称Application Not Responding,意思就是应用程序无响应
二、ANR产生的原因
1、当前事件没有得到处理,比如UI线程正在响应另一事件,当前事件由于某种原因被阻塞了
2、当前的事件正在被处理,但是由于耗时太长没有能够及时完成
三、ANR产生的本质原因
1、keydispatchtimeout:最常见的一种类型,原因是view事件或者触摸事件在5秒内未得到及时响应
2、broadcasttimeout:BroadcastReceiver的onReceive函数运行在主线程,并在特定的时间内(10s)无法完成处理
3、servicetimeout:Service的各个生命周期函数在特定时间内(20s)无法完成响应
四、典型ANR场景
1、主线程频繁进行IO操作,比如读写文件或者数据库
2、硬件操作如进行调用照相机或者录音等操作
3、多线程操作的死锁,导致主线程等待超时
4、主线程调用join()方法、sleep()方法或者wait()方法
5、耗时动画/耗资源行为导致CPU负载过重
6、system server中发生WatchDog ANR
7、service binader的数量到达了上限
五、Thread说明
Thread说明 | |||
Thread.java中定义的状态 | Thread.cpp中定义的状态 | 说明 | |
1 | TERMINATED | ZOMBIE | 线程死亡,终止运行 |
2 | RUNNABLE | RUNNING/RUNNABLE | 线程可运行或正在运行 |
3 | TIMED_WAITING | TIMED_WAIT | 执行了带有超时参数的wait、sleep或join函数 |
4 | BLOCKED | MONITOR | 线程阻塞,等待获取对象锁 |
5 | WAITING | WAIT | 执行了无超时参数的wait函数 |
6 | NEW | INITIALIZING | 新键,正在初始化,为其分配资源 |
7 | NEW | STARTING | 新键,正在启动 |
8 | RUNNABLE | NATIVE | 正在执行JNI本地函数 |
9 | WAITING | VMWAIT | 正在等待VM资源 |
10 | RUNNABLE | SUSPENDED | 线程暂停,通常是由于GC或的bug被暂停 |
11 | UNKNOWN | 未知状态 |
六、分析思路
1、logcat抓取日志命令:adb logcat -v time > C:/Users/dd/Desktop/logcat.log
(1)从logcat分析:查询关键字:ANR/ANR in com.xxx.xxx
(2)关键字所展示的内容:
导致ANR的类名及所在包名,比如:ANR in com.xxx.xxx(com.xxx.xxx/com.xxx.ui.edit.MainActivity)
导致ANR的进程名及ID,比如 PID:10228
ANR产生的原因(类型):Reason: Input dispatching timed out
系统中CPU使用率的统计信息及某段时间内的变换情况
2、从trace.txt文件分析
(1)使用命令获取trace文件:adb pull /data/anr/trace.txt
(2)在trace.txt文件中可以查看到以下信息:
应用程序包名:Cmd line:com.xxx.xxx
手机的CPU架构:ABI:‘arm64’
堆内存信息
手机Memory内存信息
(3)主线程日志分析
基本信息:main-线程名称,prio-线程优先级,tid-线程id,Waiting-线程状态
详细信息:group-线程组名称,sCount-线程被挂起的次数,dsCount-线程被调试器刮起的次数,obj-线程的Java对象地址,self-线程本身的Native对象地址
线程的调度信息:sysTid-linux系统中内核线程id(观察发现主线程的线程号和进程号相同),nice-线程调度的优先级,cgrp-线程调度组,sched-线程调度策略和优先级,handle-线程处理
上下文信息:state-线程调度状态,schedstat-线程在CPU中的执行时间、线程等待时间、线程执行的时间片长度,utm-线程在用户状态中调度的时间值,core-最后执行这个线程的CPU核序号
堆栈信息:stack-堆栈地址,stackSize-堆栈大小
余下的为堆栈信息,也是我们分析引发ANR问题的关键
由于ANR只会发生在主线程,主线程的状态也是需要关注的。