android基础(ANR)

来源:互联网 发布:腾讯数据分析 编辑:程序博客网 时间:2024/06/06 04:46

Application Not Responding

 

Android中,ActivityManagerService(简称AMS)和WindowManagerService(简称WMS)会监测应用程序的响应时间,如果应用程序主线程(即UI线程)在超时时间内对输入事件没有处理完毕,或者对特定操作没有执行完毕,就会出现ANR。对于输入事件没有处理完毕产生的ANR,Android会显示一个对话框,提示用户当前应用程序没有响应,用户可以选择继续等待或者关闭这个应用程序

 

主线程对输入事件在5秒内没有处理完毕

 

应用程序的Window处于Active状态并且能够接收输入事件(例如按键事件、触摸事件等)时,系统底层上报的事件就会被InputDispatcher分发给这个应用程序,应用程序的主线程通过InputChannel读取输入事件并交给界面视图处理,界面视图是一个树状结构,DecorView是视图树的根,事件从树根开始一层一层向端点传递。我们通常会注册一个监听器来接收并处理事件,或者创建自定义视图来处理事件

 

InputDispatcher运行在系统进程(进程名为system_server)的一个单独的线程中,应用程序的主线程在处理事件时,InputDispatcher会不断的检测处理过程是否超时,一旦超时,会通过一系列的回调通知WMS的notifyANR函数,最终会调用AMS中mHandler对象里的SHOW_NOT_RESPONDING_MSG,此时界面上就显示系统提示对话框了,同时使用logcat命令查看log(日志信息)也可以看到关于ANR的信息,InputDispatcher就是那个爱打“小报告”的家伙

 

Window:具体指的是PhoneWindow对象,表示一个能够显示的窗口,它能够接收系统分发的各种输入事件;

InputDispatcher:将系统上报的输入事件分发给当前活动的窗口;

InputChannel:InputDispatcher和应用程序分别运行在两个不同的进程中,InputDispatcher就是通过InputChannel将事件对象传递给应用进程的;

 

主线程在执行BroadcastReceiver的onReceive函数时10秒内没有执行完毕

 

对于前台广播,则超时为BROADCAST_FG_TIMEOUT,即timeout=10s;

对于后台广播,则超时为BROADCAST_BG_TIMEOUT,即timeout=60s;

 

BroadcastReceiver的onReceive函数运行在主线程中,当这个函数超过10秒钟没有返回就会触发ANR,不过对这种情况的ANR系统不会显示对话框提示,仅是输出log

 

主线程在执行Service的各个生命周期函数时20秒内没有执行完毕

 

对于前台服务,则超时为SERVICE_TIMEOUT,即timeout=20s;

对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT,即timeout=200s;

 

Service的各个生命周期函数也运行在主线程中,当这些函数超过20秒钟没有返回就会触发ANR。同样对这种情况的ANR系统也不会显示对话框提示,仅是输出log

 

三种ANR发生时都会在log中输出错误信息,你会发现各个应用进程和系统进程的函数堆栈信息都输出到了一个/data/anr/traces.txt的文件中

 

引起ANR问题的根本原因,总的来说可以归纳为两类:

 

应用进程自身引起的,例如:主线程阻塞、挂起、死循环;应用进程的其他线程的CPU占用率高,使得主线程无法抢占到CPU时间片

 

其他进程间接引起的,例如:当前应用进程进行进程间通信请求其他进程,其他进程的操作长时间没有反馈;其他进程的CPU占用率高,使得当前应用进程无法抢占到CPU时间片

 

分析ANR

 

system_server进程中的ActivityManagerService请求kernel向进程发送SIGNAL_QUIT请求,和其他Java虚拟机一样,SIGNAL_QUIT也是Dalvik内部支持的功能之一,你可以在shell中使用命令达到相同的目的:adb shell kill -3 5033

 

log中能够知道,发生ANR时Android为我们提供了两种“利器”:traces文件和CPU使用率

 

① CPU负载/平均负载

 

CPU负载是指某一时刻系统中运行队列长度之和加上当前正在CPU上运行的进程数,而CPU平均负载可以理解为一段时间内正在使用和等待使用CPU的活动进程的平均数量。CPU的负载和使用率没有必然关系,有可能只有一个进程在使用CPU,但执行的是复杂的操作;也有可能等待和正在使用CPU的进程很多,但每个进程执行的都是简单操作

 

② ANR发生之前和之后一段时间的CPU使用率

 

CPU使用率可以理解为一段时间(记作T)内除CPU空闲时间(记作I)之外的时间与这段时间T的比值

 

user: CPU在用户态的运行时间,不包括nice值为负数的进程运行的时间

nice: CPU在用户态并且nice值为负数的进程运行的时间

system:CPU在内核态运行的时间

idle: CPU空闲时间,不包括iowait时间

iowait: CPU等待I/O操作的时间

irq: CPU硬中断的时间

softirq:CPU软中断的时间

 

③ 非睡眠时间百分比

 

在记录CPU使用率的每个采样时间点时使用了两种记录方法:SystemClock.uptimeMillis()和SystemClock.elapsedRealtime(),两者的区别就是uptimeMillis不包含睡眠时间,所以两个采样时间点之间的uptimeMillis和elapsedRealtime之比就是非睡眠时间百分比。

 

➃页错误次数

 

如果ANR发生时发现CPU使用率中iowait占比很高,可以通过查看进程的页错误次数来推断是哪个进程在进行磁盘I/O操作

 

➄新增和移除的进程或线程

 

如果一个进程或线程的CPU使用率前有“+”,说明该进程或线程是在最后两次CPU使用率采样时间段内新建的;反之如果是“-”,说明该进程或线程在采样时间段内终止了;如果是空,说明该进程或线程是在倒数第二次采样时间点之前已经存在

 

Android只保留最后一次发生ANR时的traces信息,为了增强Android的异常信息收集管理能力,从2.2开始增加了DropBox功能

0 0