ANR都回答不清楚,这个X没法装下去了。更多其他完整面试专题,请关注公众号获取。
1、什么是ANR
ANR:Application Not Responding,即应用无响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。一般地,这时往往会弹出一个提示框,告知用户当前xxx未响应,用户可选择继续等待或者Force Close。
2、ANR出现场景
- Service Timeout:前台服务在20s内未执行完成,后台服务200s;
- BroadcastQueue Timeout:前台广播在10s内未执行完成,后台广播60s
- ContentProvider Timeout:内容提供者执行超时
- InputDispatching Timeout: 输入事件分发超时5s,包括按键分发事件的超时。
3、ANR超时时间在哪定义
Service Timeout
文件:ActiveServices.java
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000; // 前台 // How long we wait for a service to finish executing.
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10; // 后台
复制
Broadcast Timeout
文件:ActivityManagerService.java
// How long we allow a receiver to run before giving up on it.
static final int BROADCAST_FG_TIMEOUT = 10*1000; // 前台
static final int BROADCAST_BG_TIMEOUT = 60*1000; // 后台
复制
InputDispatching Timeout
文件:ActivityManagerService.java
// How long we wait until we timeout on key dispatching.
static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
复制
ContentProvider Timeout
// How long we wait for an attached process to publish its content providers
// before we decide it must be hung.
static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;
复制
4、ANR实现原理
主体实现在系统层,核心原理是消息调度和超时处理。经系统进程system_server调度,派发到应用进程完成对消息的实际处理,同时系统进程设计了不同的超时限制来跟踪消息的处理。一旦消息处理不当,则会触发超时限制,收集当前的系统状态,然后报告给用户有进程无响应。
Android系统ANR的实现,基本都是基于Handler消息机制来完成的。前面说过响应超时的定义,那么在一个事件执行开始时,通过Handler去post一个对应时间的延迟消息,如果事件在规定事件内执行完成,就remove掉这个message,否则,Handler就会收到这个ANR的Message,做进一步处理,dump日志,弹出ANR对话框。

5、ANR分析方法
- traces.txt文件
应用ANR产生的时候,ActivityManagerService的appNotResponding方法就会被调用,然后在/data/anr/traces.txt文件中写入ANR相关信息.最新的ANR信息在最开始部分。
- log分析
通常发生了ANR,ActivityManager会打印报错信息:ANR in com.xxx.xxxx // ANR出现的进程包名,从log中搜索“ANR in”或“am_anr”
6、traces文件位置,如何获取traces文件
- 在/data/anr/目录下
- 如果手机已经root,可以直接通过adb pull /data/anr/traces.txt d:/导出
- 没有root,网上其他方法基本都没用
- 通过adb bugreport E:\bugs导出(可行)
7、traces文件有哪些信息
- ANR的进程id、时间和进程名称。
- 线程的基本信息
- 线程的优先级(默认5)、线程锁id和线程状态
- 线程的调用栈信息(这里可查看导致ANR的代码调用流程,分析ANR最重要的信息)
8、traces文件中线程的可能状态
ThreadState (defined at “dalvik/vm/thread.h “)
THREAD_UNDEFINED = -1, /* makes enum compatible with int32_t */
THREAD_ZOMBIE = 0, /* TERMINATED */( 线程死亡,终止运行)
THREAD_RUNNING = 1, /* RUNNABLE or running now */(线程可运行或正在运行)
THREAD_TIMED_WAIT = 2, /* TIMED_WAITING in Object.wait() */(执行了带有超时参数的wait、sleep或join函数)
THREAD_MONITOR = 3, /* BLOCKED on a monitor */(线程阻塞,等待获取对象锁)
THREAD_WAIT = 4, /* WAITING in Object.wait() */( 执行了无超时参数的wait函数)
THREAD_INITIALIZING= 5, /* allocated, not yet running */(新建,正在初始化,为其分配资源)
THREAD_STARTING = 6, /* started, not yet on thread list */(新建,正在启动)
THREAD_NATIVE = 7, /* off in a JNI native method */(正在执行JNI本地函数)
THREAD_VMWAIT = 8, /* waiting on a VM resource */(正在等待VM资源)
THREAD_SUSPENDED = 9, /* suspended, usually by GC or debugger */(线程暂停,通常是由于GC或debug被暂停)
复制
9、可能导致ANR的原因
- IO操作,如数据库、文件、网络
- CPU不足,一般是别的App占用了大量的CPU,导致App无法及时处理
- 硬件操作,如camera
- 线程问题,如主线程被join/sleep,或wait锁等导致超时
- Service问题,如service忙导致超时无响应,或service binder的数量达到上限
- system server问题,如WatchDog发现ANR
10、哪些地方是执行在主线程的?
- 1.Activity的所有生命周期回调都是执行在主线程的.
- 2.Service默认是执行在主线程的.
- 3.BroadcastReceiver的onReceive回调是执行在主线程的.
- 4.没有使用子线程的Looper的Handler的handleMessage, post(Runnable)是执行在主线程的.
- 5.AsyncTask的回调中除了doInBackground, 其他都是执行在主线程的.
- 6.View的post(Runnable)是执行在主线程的.
11、日常开发中如何避免ANR
- 避免在主线程进行复杂耗时的操作,特别是文件读取或者数据库操作;
- 使用Thread或者HandlerThread时,调用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)设置优先级,否则仍然会降低程序响应,因为默认Thread的优先级和主线程相同。
- 避免频繁实时更新UI;
- BroadCastReceiver 要进行复杂操作的的时候,可以在onReceive()方法中启动一个Service来处理;
- 避免在IntentReceiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。
- 在设计及代码编写阶段避免出现出现同步/死锁或者错误处理不恰当等情况。
12、你开发中解决过的ANR问题
这个就需要各位老铁结合自己的实(fa)际(hui)经(xiang)验(xiang)来答复了,大部分人其实真实工作中是不会接触到ANR的,虽然有些东西只活在面试里,但是你也要会才行。