资讯专栏INFORMATION COLUMN

ANR详细介绍

番茄西红柿 / 2358人阅读

摘要:使用或者时,调用设置优先级,否则仍然会降低程序响应,因为默认的优先级和主线程相同。使用处理工作线程结果,而不是使用或者来阻塞主线程。

目录介绍

1.ANR简单介绍

2.ANR发生场景

3.ANR发生的原理

4.ANR有哪些具体案例

5.ANR具体如何分析

6.解决方案

7.ANR问题解答

好消息

博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计47篇[近20万字],转载请注明出处,谢谢!

链接地址:github.com/yangchong21…

如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!

1.ANR简单介绍

1.1 什么是ANR

ANR Activity not responding(页面没有响应)

ANR Application not responding 应用没有响应

Android 在4.0之后强制规定 访问网络必须开启子线程

如果在主线程访问网络,4.0之后的系统就会抛出:android.os.NetworkOnMainThreadException 在主线程联网的异常

联网的时候一定要在子线程操作,只要是耗时的操作,可能会把主线程阻塞住的操作,都要放到子线程里

主线程(UI线程)16ms,刷新一次界面,一秒60次,60贞/秒

ANR(Application Not responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。

1.2 ANR的产生需要满足三个条件

主线程:只有应用程序进程的主线程响应超时才会产生ANR;

超时时间:产生ANR的上下文不同,超时时间也会不同,但只要在这个时间上限内没有响应就会ANR;

输入事件/特定操作:输入事件是指按键、触屏等设备输入事件,特定操作是指BroadcastReceiver和Service的生命周期中的各个函数,产生ANR的上下文不同,导致ANR的原因也会不同;

2.ANR发生场景

主线程,被阻塞5秒钟以上,就会抛出ANR对话框。不同的组件发生ANR的时间不一样,Activity是5秒,BroadCastReceiver是10秒,Service是20秒(均为前台)。

点击事件(按键和触摸事件)5s内没被处理: Input event dispatching timed out

service 前台20s后台200s未完成启动 Timeout executing service

Service Timeout是位于”ActivityManager”线程中的AMS.MainHandler收到SERVICE_TIMEOUT_MSG消息时触发。

对于Service有两类:

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

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

BroadcastReceiver的事件(onRecieve方法)在规定时间内没处理完(前台广播为10s,后台广播为60s):Timeout of broadcast BroadcastRecord

以BroadcastReviever为例,在onRecieve()方法执行10秒内没发生第一种ANR(也就是在这个过程中没有输入事件或输入事件还没到5s)才会发生Receiver timeout,否则将先发生事件无相应ANR,所以onRecieve()是有可能执行不到10s就发生ANR的,所以不要在onRecieve()方法里面干活

ContentProvider的publish在10s内没进行完:timeout publishing content providers

思考一下,比如service前台是20秒,后台是200秒没响应会导致ANR,那么这个时间是哪里来的呢?

// 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;

mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);

    void serviceTimeout(ProcessRecord proc) {
    String anrMessage = null;

    synchronized(mAm) {
        if (proc.executingServices.size() == 0 || proc.thread == null) {
            return;
        }
        final long now = SystemClock.uptimeMillis();
        final long maxTime =  now -
                (proc.execServicesFg );

3.ANR发生的原理

关于ANR机制实现的原理可以先看这篇文章,个人觉得写的十分不错,可以看看:gityuan.com/2016/07/02/…

大概原理如下:

1.在进行相关操作调用hander.sendMessageAtTime()发送一个ANR的消息,延时时间为ANR发生的时间(如activity是当前时间5s之后)。

2.进行相关的操作

3.操作结束后向remove掉该条message。如果相关的操作在规定时间没有执行完成,该条message将被handler取出并执行,就发生了ANR。

4.ANR有哪些具体案例

Acitvity,Fragment中暴力相应点击事件有可能会导致ANR

断点调试时,程序可能会出现ANR无限应

主线程做了耗时操作,比如查询数据库数据导致ANR

5.ANR具体如何分析

ANR问题是由于主线程的任务在规定时间内没处理完任务,而造成这种情况的原因大致会有一下几点:

主线程在做一些耗时的工作导致线程卡死

主线程被其他线程锁

cpu被其他进程占用,该进程没被分配到足够的cpu资源。

然后看anr日志。千万别说不知道在哪里看日志,在发生ANR的时候,系统会收集ANR相关的信息提供给开发者:首先在Log中有ANR相关的信息,其次会收集ANR时的CPU使用情况,还会收集trace信息,也就是当时各个线程的执行情况。trace文件保存到了/data/anr/traces.txt中

从log中找到ANR反生的信息:会包含了ANR的时间、进程、是何种ANR等信息。

在该条log之后会有CPU usage的信息,表明了CPU在ANR前后的用量(log会表明截取ANR的时间),从各种CPU Usage信息中大概可以分析如下几点:

如果某些进程的CPU占用百分比较高,几乎占用了所有CPU资源,而发生ANR的进程CPU占用为0%或非常低,则认为CPU资源被占用,进程没有被分配足够的资源,从而发生了ANR。这种情况多数可以认为是系统状态的问题,并不是由本应用造成的。

如果发生ANR的进程CPU占用较高,如到了80%或90%以上,则可以怀疑应用内一些代码不合理消耗掉了CPU资源,如出现了死循环或者后台有许多线程执行任务等等原因,这就要结合trace和ANR前后的log进一步分析了。

如果CPU总用量不高,该进程和其他进程的占用过高,这有一定概率是由于某些主线程的操作就是耗时过长,或者是由于主进程被锁造成的。

除了上述分析CPU usage之后,确定问题需要我们进一步分析trace文件。trace文件记录了发生ANR前后该进程的各个线程的stack。对我们分析ANR问题最有价值的就是其中主线程的stack,一般主线程的trace可能有如下几种情况:

主线程是running或者native而对应的栈对应了我们应用中的函数,则很有可能就是执行该函数时候发生了超时。

主线程被block:非常明显的线程被锁,这时候可以看是被哪个线程锁了,可以考虑优化代码。如果是死锁问题,就更需要及时解决了。

由于抓trace的时刻很有可能耗时操作已经执行完了(ANR -> 耗时操作执行完毕 ->系统抓trace),这时候的trace就没有什么用了,主线程的stack就是这样的:

总结,就是两个问题

1.CPU 问题

在 Monkeylog.log 文件中定位到 "anr in" 位置,查看 cpu usage ,total 占用,如发现接近100%,暂时判断为 cpu 问题。

然后在 logcat.log 文件中定位到 "not responding" 发生时间,并截取cpuinfo.log 中时间点前后 5s 的 log,然后计算 CPU 占中,看哪个进程用的多,在酌情分析模块的 CPU 占中。

2.GC 问题

定位到 logcat.log 文件中 "not responding" 发生时间点;

去查看发生 ANR 时间点对应的 trace 文件,定位到应用报名,若Dalvik Thread主线程显示“SUSPENDED”,则为内存问题;

截取 ANR 发生时间点前 5s 的 log,分析 "dalvikvm" 打印的 Paused GC 耗时,如果过多则定位为 GC 问题,需要查看这 5s 件发生了哪些耗时的操作。

6.解决方案

将所有耗时操作,比如访问网络,Socket通信,查询大量SQL 语句,复杂逻辑计算等都放在子线程中去,然 后通过handler.sendMessage、runonUIThread、AsyncTask 等方式更新UI。无论如何都要确保用户界面作的流畅 度。如果耗时操作需要让用户等待,那么可以在界面上显示度条。

使用AsyncTask处理耗时IO操作。在一些同步的操作主线程有可能被锁,需要等待其他线程释放相应锁才能继续执行,这样会有一定的ANR风险,对于这种情况有时也可以用异步线程来执行相应的逻辑。另外, 要避免死锁的发生。

使用Thread或者HandlerThread时,调用Process.setThreadPriority(Process.THREADPRIORITYBACKGROUND)设置优先级,否则仍然会降低程序响应,因为默认Thread的优先级和主线程相同。

使用Handler处理工作线程结果,而不是使用Thread.wait()或者Thread.sleep()来阻塞主线程。

Activity的onCreate和onResume回调中尽量避免耗时的代码

BroadcastReceiver中onReceive代码也要尽量减少耗时,建议使用IntentService处理。

各个组件的生命周期函数都不应该有太耗时的操作,即使对于后台Service或者ContentProvider来讲,应用在后台运行时候其onCreate()时候不会有用户输入引起事件无响应ANR,但其执行时间过长也会引起Service的ANR和ContentProvider的ANR

7.ANR问题解答

ANR有异常日志吗?或者说ANR在第三方崩溃日志中有日志吗?

没有异常日志,因为本身不属于Error或者Exception

关于其他内容介绍

01.关于博客汇总链接

1.技术博客汇总

2.开源项目汇总

3.生活博客汇总

4.喜马拉雅音频汇总

5.其他汇总

02.关于我的博客

我的个人站点:www.yczbj.org,www.ycbjie.cn

github:github.com/yangchong21…

知乎:www.zhihu.com/people/yang…

简书:www.jianshu.com/u/b7b2c6ed9…

csdn:my.csdn.net/m0_37700275

喜马拉雅听书:www.ximalaya.com/zhubo/71989…

开源中国:my.oschina.net/zbj1618/blo…

泡在网上的日子:www.jcodecraeer.com/member/cont…

邮箱:yangchong211@163.com

阿里云博客:yq.aliyun.com/users/artic… 239.headeruserinfo.3.dT4bcV

segmentfault头条:segmentfault.com/u/xiangjian…

项目地址:github.com/yangchong211

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/7035.html

相关文章

  • ANR详细介绍

    摘要:使用或者时,调用设置优先级,否则仍然会降低程序响应,因为默认的优先级和主线程相同。使用处理工作线程结果,而不是使用或者来阻塞主线程。目录介绍 1.ANR简单介绍 2.ANR发生场景 3.ANR发生的原理 4.ANR有哪些具体案例 5.ANR具体如何分析 6.解决方案 7.ANR问题解答 好消息 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,P...

    wslongchen 评论0 收藏0
  • Android 2019最新面试实战总结

    摘要:内存泄漏当应用内部不再需要某个实例后,但是这个对象却仍然被引用,这个情况就叫做内存泄露。安卓虚拟机为每一个应用分配一定的内存空间,当内存泄露到达一定的程度就会造成内存溢出。点击登录跳转页面中所有操作都与用户密切相关,是 Android: 今日头条屏幕适配的原理? 1:首先计算出 density,计算公式:当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = densit...

    whataa 评论0 收藏0
  • Android 2019最新面试实战总结

    摘要:内存泄漏当应用内部不再需要某个实例后,但是这个对象却仍然被引用,这个情况就叫做内存泄露。安卓虚拟机为每一个应用分配一定的内存空间,当内存泄露到达一定的程度就会造成内存溢出。点击登录跳转页面中所有操作都与用户密切相关,是 Android: 今日头条屏幕适配的原理? 1:首先计算出 density,计算公式:当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = densit...

    Caicloud 评论0 收藏0
  • 金九银十中,看看这31道Android面试题

    摘要:静态集合类引起内存泄露主要是,等,如果是静态集合这些集合没有及时的话,就会一直持有这些对象。关于合理使用内存,其实就是避免内存泄露中已经说明。参数原生参数元素需要支持机制参考进程线程管理一消息机制的框架这个系类。 阅读目录 1.如何对 Android 应用进行性能分析 2.什么情况下会导致内存泄露 3.如何避免 OOM 异常 4.Android 中如何捕获未捕获的异常 5.ANR 是...

    call_me_R 评论0 收藏0
  • Android性能优化9-ANR完全解析

    摘要:产生的原因产生的根本原因是阻塞了线程。让耗时的工作比如数据库操作,,连接网络或者别的有可能阻碍线程的操作把它放入单独的线程处理。1.什么是ANR 在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应用程序时,...

    mozillazg 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<