Android 系统稳定性 - ANR(一)
文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任。
很久之前写的了,留着有点浪费,共享之。
编写者:李文栋
如果你是一个Android应用程序开发人员,你的人生中不可避免的三件事情是:死亡、缴税和ANR。这么说是夸张了,但是由于Android本身的设计,以及应用程序和系统在开发过程中的缺陷,经常会在测试过程中遇到各种各样的ANR问题。在功能性的测试中还少一些,主要是在压力测试中(例如Monkey测试)会遇到非常多的ANR问题。本章的目的就是汇总笔者在工作中遇到的各种ANR问题,将其归纳总结出一套分析和处理ANR问题的方法,希望能够通过这套方法为大家提供思路,有效的减少大家处理ANR问题的时间。同时也会给出一些避免ANR的最佳实践,更多的从预防做起,更少的做事后补救。
考虑到看本文的读者大多是有实际经验的开发人员,我会尽量少的提到一些基础的概念,我也希望给大家更多的“干货”。
本章的主要内容如下:
ANR简介(什么是ANR、为什么会有ANR、ANR的异常长什么样)
如何分析ANR(引起ANR的原因分类、分析ANR的利器)
实例讲解
避免ANR的最佳实践(从错误中吸取教训)
1.1 ANR简介
ANR,是“Application Not Responding”的缩写,即“应用程序无响应”。在Android中,ActivityManagerService(简称AMS)和WindowManagerService(简称WMS)会监测应用程序的响应时间,如果应用程序主线程(即UI线程)在超时时间内对输入事件没有处理完毕,或者对特定操作没有执行完毕,就会出现ANR。对于输入事件没有处理完毕产生的ANR,Android会显示一个对话框,提示用户当前应用程序没有响应,用户可以选择继续等待或者关闭这个应用程序(也就是杀掉这个应用程序的进程)。
1.1.1 为什么会有ANR
如上所述,ANR的产生需要同时满足三个条件:
主线程:只有应用程序进程的主线程响应超时才会产生ANR;
超时时间:产生ANR的上下文不同,超时时间也会不同,但只要在这个时间上限内没有响应就会ANR;
输入事件/特定操作:输入事件是指按键、触屏等设备输入事件,特定操作是指BroadcastReceiver和Service的生命周期中的各个函数,产生ANR的上下文不同,导致ANR的原因也会不同;
针对这三个条件,有以下三种情况会触发ANR,详细说明如下。
1.主线程对输入事件在5秒内没有处理完毕
Android的事件系统从2.3开始做了完全不同的实现,原先2.2中是在Java层实现的,但在2.3中整体转移到了C++层,本书基于2.3以后的版本进行说明。我们先简单了解一下产生这种ANR的整个流程<!-- 在这章之前要先讲Android的事件机制?还是放在后一章讲?偏向于放在后面。 -->。
当应用程序的Window处于Active状态并且能够接收输入事件(例如按键事件、触摸事件等)时,系统底层上报的事件就会被InputDispatcher分发给这个应用程序,应用程序的主线程通过InputChannel读取输入事件并交给界面视图处理,界面视图是一个树状结构,DecorView是视图树的根,事件从树根开始一层一层向端点(例如一个Button)传递。我们通常会注册一个监听器来接收并处理事件,或者创建自定义的视图控件来处理事件。
InputDispatcher运行在系统进程(进程名为system_server)的一个单独的线程中,应用程序的主线程在处理事件的过程中,InputDispatcher会不断的检测处理过程是否超时,一旦超时,会通过一系列的回调通知WMS的notifyANR函数,最终会调用到AMS中mHandler对象里的SHOW_NOT_RESPONDING_MSG这个case,此时界面上就显示系统提示对话框了,同时使用logcat命令查看log(日志信息)也可以看到关于ANR的信息。InputDispatcher就是那个爱打“小报告”的家伙。
一下子出现了好几个重要的名词,要深入了解这种情况的ANR,需要熟悉Android的事件机制,本书会在别的章节中详细分析,这里只需要记住他们的功能:
Window:具体指的是PhoneWindow对象,表示一个能够显示的窗口,它能够接收系统分发的各种输入事件;
InputDispatcher:将系统上报的输入事件分发给当前活动的窗口;
InputChannel:InputDispatcher和应用程序分别运行在两个不同的进程中,InputDispatcher就是通过InputChannel将事件对象传递给应用进程的。
注意:产生这种ANR的前提是要有输入事件,如果用户没有触发任何输入事件,即便是主线程阻塞了,也不会产生ANR,因为InputDispatcher没有分发事件给应用程序,当然也不会检测处理超时和报告ANR了。
2.主线程在执行BroadcastReceiver的onReceive函数时10秒内没有执行完毕
BroadcastReceiver(简称BR)的onReceive函数运行在主线程中,当这个函数超过10秒钟没有返回就会触发ANR。不过对这种情况的ANR系统不会显示对话框提示,仅是输出log而已。
3.主线程在执行Service的各个生命周期函数时20秒内没有执行完毕
Service的各个生命周期函数也运行在主线程中,当这些函数超过20秒钟没有返回就会触发ANR。同样对这种情况的ANR系统也不会显示对话框提示,仅是输出log。
三种ANR中只有第1种会显示系统提示对话框,因为用户正在做界面交互操作,如果长时间没有任何响应,会让用户怀疑设备死机了,大多数人此时会开始乱按,甚至拔出电池重启,给用户的体验肯定是非常糟糕的。
三种ANR发生时都会在log中输出错误信息,你会发现各个应用进程和系统进程的函数堆栈信息都输出到了一个/data/anr/traces.txt的文件中,这个文件是分析ANR原因的关键文件,同时在日志中还会看到当时的CPU使用率,这也是重要信息,在后面的章节会详细介绍如何利用它们分析ANR问题。
这三种ANR不是孤立的,有可能会相互影响。例如一个应用程序进程中同时有一个正在显示的Activity和一个正在处理消息的BroadcastReceiver,它们都运行在这个进程的主线程中。如果BR的onReceive函数没有返回,此时用户点击屏幕,而onReceive超过5秒仍然没有返回,主线程无法处理用户输入事件,就会引起第1种ANR。如果继续超过10秒没有返回,又会引起第2种ANR。
Android 系统稳定性 - ANR(一)的更多相关文章
- Android 系统稳定性 - ANR(二)(转)
编写者:李文栋P.S. OpenOffice粘贴过来后格式有些混乱. 1.2 如何分析ANR问题 引起ANR问题的根本原因,总的来说可以归纳为两类: 应用进程自身引起的,例如: 主线程阻塞.挂起.死循 ...
- 【原创】Android 系统稳定性 - ANR(二)
文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任. 很久之前写的了,留着有点浪费,共享之.编写者:李文栋P.S. OpenOffice粘贴过来后格式有些混乱. 1.2 如何分析ANR问题 引 ...
- [转发]Android 系统稳定性 - ANR(二)
文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任. 很久之前写的了,留着有点浪费,共享之.编写者:李文栋P.S. OpenOffice粘贴过来后格式有些混乱. http://rayleeya ...
- [转发]Android 系统稳定性 - ANR(一)
文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任.很久之前写的了,留着有点浪费,共享之.编写者:李文栋 http://rayleeya.iteye.com/blog/1955652 如果你 ...
- [转发]Android 系统稳定性 - ANR(三)
文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任. 很久之前写的了,留着有点浪费,共享之. 编写者:李文栋 http://rayleeya.iteye.com/blog/1956056 1. ...
- 【转】Android系统开篇
版权声明:本站所有博文内容均为原创,转载请务必注明作者与原文链接,且不得篡改原文内容.另外,未经授权文章不得用于任何商业目的. 一.引言 Android系统非常庞大.错综复杂,其底层是采用Linux作 ...
- Android客户端稳定性测试——Monkey
修改时间 修改内容 修改人 2016.6.20 创建 刘永志 2016.6.29 完成 刘永志 Monkey简介: Android SDK自带的命令行测试工具,向设备发送伪随机事件流,对应用程序进行进 ...
- Android中的ANR
有过Android开发经历的人都不会对ANR陌生,它和崩溃一样是程序设计的问题.本文将以较为深入的视角来介绍什么是ANR,出现场景,如何避免以及如何定位分析ANR,希望可以帮助大家在编写程序时有所帮助 ...
- Android系统中的广播(Broadcast)机制简要介绍和学习计划
在Android系统中,广播(Broadcast)是在组件之间传播数据(Intent)的一种机制:这些组件甚至是可以位于不同的进程中,这样它就像Binder机制一样,起到进程间通信的作用:本文通过一个 ...
随机推荐
- ubutun 下webalizer 分析Apache日志
http://www.webalizer.org/ 配置Webalizer 我们可以通过命令行配置Webalizer,也可以通过配置文件进行配置.下面将重点介绍使用配置文件进行配置,该方法使用形式比 ...
- cocos2d-x中的导演、场景、层和精灵
场景(Scenes) 场景在cocos2d-x中是CCScene类实现的,是应用程序流中独立的一部分.一个cocos2dx应用程序可以有许多场景,但是在某一时刻,只有一个场景在运行. 比如,你有一个游 ...
- podoWeb极品流氓软件
用firefox做页面网络性能测试, 打开网页就会发现页面不停的去请求googleapi.com上的jquery Or swfobject.js,页面就此卡住,一直在等待类似这两个请求的返回,知道Ab ...
- PHP第一章学习——了解PHP(上)
计划开启PHP学习教程,情况如下: 1.采用教程35章48个视频文件 2.时间4月29日-5月6日 共计8天 3.具体划分每天学习章节数不少于5个,预留5-6号时间为五一假期出玩情况 4.要求认真学习 ...
- Struts2 学习笔记19 类型转换 Part1
现在来说一说类型转换,提到类型转换其实我们之前早已经用过了,在url传递参数的时候,我们传递过来的参数其实都是String类型的,在显示的时候都自动转换了,像这种简单的转换很好理解,我们要说的是,转换 ...
- STL之string
string构造函数,很多重载函数: #include <iostream> #include <string> using namespace std; int main() ...
- javascript事件及事件传输
函数必须调用才能执行,可a()加下面的函数调用 JS事件 1.js事件通常和函数结合来使用,这样可以通过发生的事件来驱动函数的执行,从而引起html出现不同的效果. 2.属性(当这些事件的属性发生时, ...
- C#中继承,集合(Eleventh day)
又到了总结知识的时间,今天在云和学院继续学习了继承的一些运用,和集合的运用.下面就总结下来吧 理论: 显示调用父类的构造方法,关键字: base:构造函数不能被继承:子类对象被实例化的时候会先去主动的 ...
- JavaSE学习总结第20天_IO流2
20.01 递归概述和注意事项 递归:方法定义中调用方法本身的现象 递归注意事项: 1.要有出口,否则就是死递归 2.次数不能太多,否则就内存溢出 3.构造方法不能递归使用 20.02 递归求 ...
- 如何隐藏DLL中,导出函数的名称?
一.引言 很多时候,我们写了一个Dll,不希望别人通过DLL查看工具,看到我们的导出函数名称.可以通过以下步骤实现: 1. 在def函数中做如下定义: LIBRARY EXPORTS HideFunc ...