文档开发者中心
我的

ANR分类及常见场景

1. ANR概述

ANR的全称是Application No Responding,即应用程序无响应,具体是一些特定的Message(Key Dispatch、Broadcast、Service)在应用的UI线程(主线程)没有在规定的时间内处理完,进而触发ANR异常。

ANR由消息处理机制保证,Android在系统层实现了一套精密的机制来发现ANR,核心原理是消息调度和超时处理。ANR机制主体实现在系统层,所有与ANR相关的消息,都会经过系统进程system_server调度,具体是ActivityManagerService服务,然后派发到应用进程完成对消息的实际处理,同时,系统进程设计了不同的超时限制来跟踪消息的处理。 一旦应用程序处理消息不当,超时限制就起作用了,它收集一些系统状态,譬如CPU/IO使用情况、进程函数调用栈,最后报告用户有进程无响应了(ANR对话框)。


2. ANR分类

ANR一般有三种类型:

a. KeyDispatchTimeout (默认5s,主要类型)

这个主要是按键或触摸事件在特定时间内无响应,一般Android平台默认超时时间是5s会报anr,不过有些平台会修改这个时间,比如MTK有些平台就是8s的超时时间。这类超时会有ANR提示框弹出,用户可以选择forceStop或者继续等待。

b. BroadcastTimeout (默认 前台10s、后台60s)

这个主要是BroadcastRecevier在规定时间无法处理完成。前台广播超时时间是10s,后台广播超时是60s,这类超时没有提示框弹出。

c. ServiceTimeout (默认 前台20s、后台200s 小概率类型)

Service在规定时间内无法处理完成操作,即会报出服务超时,这类ANR同样没有提示框出现。超时时间,前台Service是20s,后台Service是200s。

3. 哪些场景会出现ANR

场景1:低内存anr:查看CPU,手机内存低导致anr时,一般以下两个进程CPU使用率高,手机会出现大量应用anr:

35% 90/mmcqd/0: 0% user + 35% kernel

18% 49/kswapd0: 0% user + 18% kernel

场景2: 某一个进程的cpu使用率高,导致当前进程无法获取资源,可以根据trace查看是哪个进程在工作;

场景3:主线程卡死: 1)主线程等待其他线程锁waiting to lock; 2) 主线程繁忙;3)主线程对应的native调用栈卡住;

场景4:Activity resume、restart或pause太慢,导致无焦点窗口问题,通常会有黑屏白屏等现象;

场景5:省电精灵智能省电模式冻结后台进程,resume activity时,没有及时解冻,产生无焦点窗口anr;

场景6:其它进程Binder线程耗尽(ProcessState.cpp中指定最大binder线程数,如maxThreads:32),导致当前进程卡在IPCThreadState::talkWithDriver;

场景7:Input dispatching timed out:接收输入事件的窗口出现异常,丢失焦点,伴随冻屏现象

场景8:monkey启动大量对象GC耗时久导致anr。从dumpsys中可以看到启动很多window,从log中看GC耗时很久;

场景9:抓取整机log导致anr。此类问题中,adbd、bugreport、chargelogcat等进程CPU使用率高;

场景10:Framework缺陷导致无焦点窗口问题,activity已经正常resume了(am_on_resume_called),dumpsys中mFocusedWindow为null。


点赞
1
收藏
1
回复
2
分享
举报
浏览7584 发布于2019-07-15 01:43未知归属地
全部评论
最多点赞
最新发布
最早发布

一、常见ANR问题分类

我们经常遇见的ANR大致分为以下几类:

1、主线程操作超时ANR

比如在主线程执行IO操作,设置里面经常容易出现此类ANR问题的主要在存储页面,在存储页面会读取当前手机的可用存储设备,如果当前插入手机的SD卡有损坏导致读取速度过慢,就会出现长时间执行导致的ANR,这一类ANR一般比较容易定位解决,丢到子线程执行即可。

2、Binder调用阻塞ANR

在开发过程中,经常会调用一些系统接口,android里大部分系统服务都是以service的形式提供的,所以经常会用到binder调用,一般来说这些调用都会很快的返回,不属于耗时操作,所以不会放到子线程执行。但是时长会出现被调用侧发生死锁等问题导致长时间不返回,进而导致应用ANR。此类问题一般由被调用侧处理,但是得应用先行分析定位。

3、系统响应过慢ANR

这一类ANR比较麻烦,通常是在系统当前处于一种异常状态,用户去使用应用,导致应用出现ANR,所以看不出任何报错堆栈,要同时分析一些其他信息来帮助确认问题,具体方法在 ANR问题分析方法及步骤 里细说

4、事件分发长时间处理ANR

还有一类比较麻烦需要花时间分析的就是input dispatching timed out这种ANR了,导致ANR的原因多种多样,可能是应用本身卡顿,也可能是系统卡顿,导致安卓下发了事件,事件在队列中长时间不被消费,就会抛出这一类异常


二、ANR问题分析方法及步骤

我们分析ANR问题主要查看两种log文件,一种是dropbox里的anr log,比如我们设置是系统应用,就看system_app_anr。通常上面列举的1、2两类问题,通过这个文件就可以直接定位出来了。接下来就是我们常分析的applog,分析3、4类问题就需要它的辅助了。

1、ANR log的文件结构以及分析方法

这里们只说明一下几个比较重要的文件结构

首先我们看文件头,示例如下:

从文件头主要有如下几个关键信息

(1)报错应用包名 和 进程名

有这两个信息我们可以知道是不是我们的应用,已经在applog里查看我们应用进程打印的log

(2)问题类型

通过这个我们可以来识别是什么问题,这个对应的就是我们说的第3类问题了


第二步我们搜索blocked,一般在anr log底部可以看到如下信息。

在这里我们可以看到所有被阻塞的binder调用,在这里面我们就可以找有没有我们的主线程被阻塞的调用

这份log里第一个就是的

可以看到当前设置正在调用蓝牙的binder调用,被调用的binder编号为1001_4


从这里我们就可以判断当前是对蓝牙的调用阻塞了,但是我们还可以进一步分析具体阻塞点,直接搜索1001_4可以看到队友binder在做什么

通常我们可以看到binder里存在死锁,比如说存在waiting to lock XXXX,这个时候搜索XXXX这个锁被谁持有,搜索XXXX就可以看到locked XXXX的地方,进一步判断是否有死锁


但是这个log里什么都看不出来,我们就可以换一个方向,搜索main

这个可以看到当前进程的主线程是执行到哪个调用被阻塞的,我们可以看到是蓝牙的getType函数


其实如果是情况1的话,进anr log直接搜索main,看主线程对应的堆栈调用卡在哪里就行,

注意,main这个主线程打印出来的堆栈只是抓取anr log时进程主线程执行的情况,除非第一行的Native 显示为block,否则不能直接证明就行停在当前的调用上,需要blocked binder trasaction来辅证。


接下来就是比较麻烦的系统卡住的情况了,这时候anr log里还有个信息可以看看,那就是文件头下的CPU使用情况了

从这个我们可以查看当前系统是否是高负载状态,但是也仅仅能做辅助,不能做直接证明作用。


2、applog辅助分析ANR问题

anr问题有个特点,就是出问题要等几秒(主线程5s,后台线程30s)才报错,所以不像crash问题那样有实时性。

分析applog主要是看系统整体的状态。


首先我们可以搜索ANR 或者 kill -9 或者anr log的进程号,来看我们的应用是什么时候ANR被干掉了,然后看附近的应用状态log

比较有用的TAG我列举一下:

1、BlockMonitor:应用阻塞则会打印这个,看是不是大批量的BlockMonitor打印,来证明当前系统很卡。

2、IAware:iaware会打各种各样的log,比如页面显示啊,内存状态啊,虽然它很烦,没事还杀一下我们的进程,但是定位问题还是有点帮助的。我们经常可以看到内存占用多回收内存的log,说明当前内存已经不够用,属于高负荷状态。

3、watchdog:system server有阻塞的时候就会打这个,用这个也可以做辅助证明


展开全部
2楼编辑于2020-07-16 06:28 未知归属地

感谢楼主分享

1楼回复于2019-07-15 02:35 未知归属地
写回答
新增插入模板功能
一键使用模板,快速填写内容,轻松发帖~
知道了
  • 为了保障您的信息安全,请勿上传您的敏感个人信息(如您的密码等信息)和您的敏感资产信息(如关键源代码、签名私钥、调试安装包、业务日志等信息),且您需自行承担由此产生的信息泄露等安全风险。
  • 如您发布的内容为转载内容,请注明内容来源。

我要发帖子

了解社区公约,与您携手共创和谐专业的开发者社区。