189 8069 5689

android的anr,android的anr机制

Android ANR 机制

广播的 ANR 处理相对简单,主要是再次判断是否超时、记录日志,记录 ANR 次数等。然后就继续调用 processNextBroadcast 函数,处理下一条广播了。

创新互联公司-专业网站定制、快速模板网站建设、高性价比万全网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式万全网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖万全地区。费用合理售后完善,10多年实体公司更值得信赖。

ContentProvider 超时为 CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s

Activity 的 ANR 是相对最复杂的,也只有 Activity 中出现的 ANR 会弹出 ANR 提示框。

最终的表现形式是:弹出一个对话框,告诉用户当前某个程序无响应,输入一大堆与 ANR 相关的日志,便于开发者解决问题。

InputDispatching:

Activity 最主要的功能之一是交互,为了方便交互,Android 中的 InputDispatcher 会发出操作事件,最终在 InputManagerService 中发出事件,通过 InputChannel,向 Activity 分发事件。交互事件必须得到响应,如果不能及时处理,IMS 就会报出 ANR,交给 AMS 去弹出 ANR 提示框。

KeyDispatching:

如果输入是个 Key 事件,会从 IMS 进入 ActivityRecord.Token.keyDispatchingTimeOut,然后进入 AMS 处理,不同的是,在 ActivityRecord 中,会先截留一次 Key 的不响应,只有当 Key 连续第二次处理超时,才会弹出 ANR 提示框。

窗口焦点:

Activity 总是需要有一个当前窗口来响应事件的,但如果迟迟没有当前窗口(获得焦点),比如在 Activity 切换时,旧 Activity 已经 onPause,新的 Activity 一直没有 onResume,持续超过 5 秒,就会 ANR。

App 的生命周期太慢,或 CPU 资源不足,或 WMS 异常,都可能导致窗口焦点。

1. 判断是否有 focused 组件以及 focused Application:

这种一般是在应用启动时触发,比如启动时间过长在这过程中触发了 keyevent 或者 trackball moteionevent 就会出现。

对应于

2. 判断前面的事件是否及时完成:

对应于

出现这种问题意味着主线程正在执行其他的事件但是比较耗时导致输入事件无法及时处理。

InputDispatcher 超时是最常见的 ANR 类型,而且其类型也比较多。

当用户触摸屏幕或者按键操作,首次触发的是硬件驱动,驱动收到事件后,将该相应事件写入到输入设备节点, 这便产生了最原生态的内核事件。接着,输入系统取出原生态的事件,经过层层封装后成为 KeyEvent 或者 MotionEvent ;最后,交付给相应的目标窗口(Window)来消费该输入事件。可见,输入系统在整个过程起到承上启下的衔接作用。

Input 模块的主要组成:

每一个应用进程都会有一个 SignalCatcher 线程,专门处理 SIGQUIT,来到 art/runtime/signal_catcher.cc :

当应用发生 ANR 之后,系统会收集许多进程,来 dump 堆栈,从而生成 ANR Trace 文件。收集的第一个,也是一定会被收集到的进程,就是发生 ANR 的进程。接着系统开始向这些应用进程发送 SIGQUIT 信号,应用进程收到 SIGQUIT 后开始 dump 堆栈。

[1] developer ANRs

[2] Android ANR 分析详解

[3] 看完这篇 Android ANR 分析,就可以和面试官装逼了!

[4] 微信 Android 团队手把手教你高效监控 ANR

[5] Input 系统—ANR 原理分析 - Gityuan

[6] 彻底理解安卓应用无响应机制 - Gityuan

[7] 理解 Android ANR 的触发原理 - Gityuan

android anr怎么解决

ANR (Application Not Responding)

ANR定义:在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择“等待”而让程序继续运行,也可以选择“强制关闭”。所以一个流畅的合理的应用程序中不能出现anr,而让用户每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要,这样系统不会显示ANR给用户。

默认情况下,在android中Activity的最长执行时间是5秒,BroadcastReceiver的最长执行时间则是10秒。

第一:什么会引发ANR?

在Android里,应用程序的响应性是由Activity Manager和WindowManager系统服务监视的 。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:

1.在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)

2.BroadcastReceiver在10秒内没有执行完毕

造成以上两点的原因有很多,比如在主线程中做了非常耗时的操作,比如说是下载,io异常等。

潜在的耗时操作,例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者以数据库操作为例,通过异步请求的方式)来完成。然而,不是说你的主线程阻塞在那里等待子线程的完成——也不是调用 Thread.wait()或是Thread.sleep()。替代的方法是,主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。以这种方式设计你的应用程序,将能保证你的主线程保持对输入的响应性并能避免由于5秒输入事件的超时引发的ANR对话框。

第二:如何避免ANR?

1、运行在主线程里的任何方法都尽可能少做事情。特别是,Activity应该在它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。(可以采用重新开启子线程的方式,然后使用Handler+Message的方式做一些操作,比如更新主线程中的ui等)

2、应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在子线程里做这些任务(因为 BroadcastReceiver的生命周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个 Service。(此处需要注意的是可以在广播接受者中启动Service,但是却不可以在Service中启动broadcasereciver,关于原因后续会有介绍,此处不是本文重点)

3、避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。

总结:anr异常也是在程序中自己经常遇到的问题,主要的解决办法自己最常用的就是不要在主线程中做耗时的操作,而应放在子线程中来实现,比如采用Handler+mesage的方式,或者是有时候需要做一些和网络相互交互的耗时操作就采用asyntask异步任务的方式(它的底层其实Handler+mesage有所区别的是它是线程池)等,在主线程中更新UI。

Android ANR产生的原因和分析

ANR: ANR全称是Application No Responding,翻译过来就是程序无响应, 他是Android独有的概念。定位和解决以及避免ANR是我们需要必备的技能。

1: ANR产生的原因:

Android的UI线程响应超时就会引起ANR, 主要体现在两种情况中:

2:典型的ANR场景:

1: 当一个ANR的问题产生, 我们无法确认是ANR watchdog或者是crash。每一种类型的问题的产生都有不同的影响范围和表现形态, 一般冻屏, 一段时间后程序退出, 这种情况的产生都是ANR。在我们的AP Log中,ANR的filter字段一般有这几种: ANR low_memory slow_operation. 我们根据这些关键字搜索到发生ANR的地方:

2: ANR log日志在系统的data/anr目录下, 我们将所有的anr log日志pull出来。

3: 打开这个文件

如何分析解决Android ANR

引发ANR的原因:

在Android里,应用程序的响应性是由Activity Manager和WindowManager系统服务监视的 。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:

1.在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)

2.BroadcastReceiver在10秒内没有执行完毕

造成以上两点的原因有很多,比如在主线程中做了非常耗时的操作,比如说是下载,io异常等。

潜在的耗时操作,例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者以数据库操作为例,通过异步请求的方式)来完成。然而,不是说你的主线程阻塞在那里等待子线程的完成——也不是调用 Thread.wait()或是Thread.sleep()。替代的方法是,主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。以这种方式设计你的应用程序,将能保证你的主线程保持对输入的响应性并能避免由于5秒输入事件的超时引发的ANR对话框。

Android ANR,看完不慌

隔壁部门做了一个评价器,就是一个jsp页面在安卓设备上一直运行,安卓原生部分的很简单,就是通过webview加载,打了个apk。最近用户反馈说在运行一段时间后,有时4-5个小时,有时10几个小时,再次点击页面就会出现程序无响应的情况。于是找到我这边给测试解决,说真的,我比较慌。

1.设备的问题(因为集中采购的是一些奇奇怪怪的设备)。

WebSettings的相关配置也是添加的

tWebChromeClient 及WebViewClient相关也是设置了的,看起来也没啥问题。

3.页面的问题。

页面不是我写的,没证据不能讲。

假设被推翻,出问题的时间也没法确定,看来捷径是走不通了,只能从抓日志下手了,这里用了友盟统计的sdk去帮助完成这一步,等待两天之后,错误日志收获满满,还是比较兴奋的。

待俺赶上前去,选取一条仔细观瞧,不由得一身冷汗,尴尬了,看不懂。

莫慌,看不不要紧,根据指导原则猜猜也是有用的。

[DEBUG] runtime trace: 33,20,/data/anr/traces.txt 这句告诉我们anr日志保存路径(没卵用)

main prio=7 tid=1 Native main 表示主线程 prio线程优先级 tid不是线程的id,它是一个在Java虚拟机中用来实现线程锁的变量,随着线程的增减,这个变量的值是可能被复用的. Native不必多说。

tid对应值解释说明

group是线程组名称。sCount是此线程被挂起的次数,dsCount是线程被调试器挂起的次数,当一个进程被调试后,sCount会重置为0,调试完毕后sCount会根据是否被正常挂起增长,但是dsCount不会被重置为0,所以dsCount也可以用来判断这个线程是否被调试过。obj表示这个线程的Java对象的地址,self表示这个线程本身的地址。

此后是线程的调度信息

sysTid是Linux下的内核线程id,nice是线程的调度优先级,sched分别标志了线程的调度策略和优先级,cgrp是调度属组,handle是线程的处理函数地址。

然后是线程当前上下文信息

state=S schedstat=( 303590361913 618664734427 651535 ) utm=19466 stm=10893 core=0

state是调度状态;schedstat从 /proc/[pid]/task/[tid]/schedstat读出,三个值分别表示线程在cpu上执行的时间、线程的等待时间和线程执行的时间片长度,有的android内核版本不支持这项信息,得到的三个值都是0;utm是线程用户态下使用的时间值(单位是jiffies);stm是内核态下的调度时间值;core是最后执行这个线程的cpu核的序号。

最后就是这个线程的调用栈信息。

看了日志文件,对于如何找出ANR的真正原因,还是一件难事,其实说难不难,文本冗长我们没必要弄懂每一行的意思,一般的,如果是我们的应用造成的anr,至少能够在这个文件里看到包名com.xxx.xx的表述,结合上下文分析应该不难,但我这个没找到。

除了找应用信息,查找wating ,anr等关键字,因为anr的情况一般是让主线程做了很多耗时的操作,我这个是应用长驻的,放在柜台员前让办事用户再办完事情进行评价的,很简答的功能,原生并没有耗时操作,jsp页面问了问写的人员也没有做耗时操作,这就很奇怪。

苦苦阅读这个anr日志时,事情出现了转机,外派员反馈另一个地区的设备是来自不同厂商的,出现问题后厂商过来给设备进行过处理,目前那一批设备是好的(为啥不早说),于是联系那边询问,做了什么骚操作,发来了一个文件夹:

简单看了看,主要是给更新了WebViewGoogle_arm32.apk,手机上是见过这东西的,开发者选项下查看`webView实现'就能够看到,小米华为都有,然而我手里这台设备在设置里搜寻一圈都没有(什么鬼设备)


名称栏目:android的anr,android的anr机制
当前链接:http://cdxtjz.cn/article/dseidhi.html

其他资讯