Android---ANR问题分析

news/2024/7/16 8:15:47 标签: android, android studio, ide

目录

ANR 概念

超时检测机制

如何避免 ANR 问题?

ANR 分析

ANR 问题线上监控


ANR 概念

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

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

\bullet Service Timeout

\bullet BroadcastQueue Timeout

\bullet ContentProvider Timeout

\bullet InputDispatching Timeout

Timeout 时长

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

\bullet 对于后台服务,超时则为:SERVICE_BACKGROUND_TIMEOUT = 200s;

\bullet 对于前台广播,超时则为:BROADCAST_FG_TIMEOUT = 10s;

\bullet 对于后台广播,则超时为:BROADCAST_BG_TIMEOUT = 60s;

\bullet ContentProvider 超时为 CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s;

\bullet InputDispatching Timeout: 输入事件分发超时 5s ,包括按键和触摸事件

注意:Input 的超时机制与其它的不同,对于 Input 来说即便某次事件执行时间超过 timeout 时长,只要用户后续没有再生成输入事件,则不会触发 ANR。

超时检测机制

1. Service 超时检测机制:

        超过一定时间没有执行完相应操作来触发移除延时信息,则会触发 ANR;

2. BroadcastReceiver 超时检测机制:

        有序广播的总执行时间超过 2*receiver 个数 * timeout 时长,则会触发 ANR;

        有序广播的某一个 receiver 执行过程超过 timeout 时长,则会触发ANR;

3. 另外:

        对于 Service,Broadcast,input 发生 ANR 之后,最终都会调用 AMS.appNotResponding; 

        对于 provider, 在其进程启动时 publish 过程可能会出现 ANR,则会直接杀进程以及清理相应

        信息,而不会弹出 ANR 对话框;

如何避免 ANR 问题?

考虑上面的 ANR 定义,让我们来研究一下为什么它会在 Android 应用程序里发生和如何构建最佳应用程序来避免 ANR。

1. Android 应用程序通常是运行在一个单独的线程(例如,main)里。这意味着你的应用程序所做事情如果在主线程里占用了台词的时间的话,就会引发 ANR 对话框,因为你的应用程序并没有给自己机会来处理输入事件或者 Intent 广播。

2. 运行在主线程里的任何方法都尽可能少做事情。特别是,Activity 应该在它的关键生命周期方法(如 onCreate() 和 onResume())里尽可能少的去做创建操作。潜在的耗时操作,如网络数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里来完成。然而,不是说你的主线程阻塞在哪里等待子线程的完成,也不是调用 Thread.wait() 或者 Thread.sleep()。代替的方法是,主线程应该为子线程提供一个 Handler,以便完成时能够提交给主线程。以这种方式设计你的应用程序,将能保证你的主线程保持对输入的响应性并能避免由于 5s 输入事件的超时引发的 ANR 对话框。这种做法应该在其它显示 UI 的线程里效仿,因为它们都受到相同的超时影响。

3. IntentReceiver 执行时间的特殊限制意味着它应该做:在后台里做小的、琐碎的工作如保存设定或者注册一个 Notification。和在主线程里调用的其它方法一样,应用程序应该避免在 BroadcastReceiver 里做耗时的操作或计算。但不再是在子线程里做这些任务(因为 BroadcastReceiver 的生命周期短),代替的是,如果响应 Intent 广播需要执行一个耗时的动作的话,应用程序应该启动一个 Service。同时,也应该避免在 IntentReceiver 里启动一个 Activity ,因为它会创建一个新的画面,并从当前用户正在运行的程序抢夺焦点。如果你的应用程序在响应 Intent 广播是需要向用户展示什么,你应该使用 Notification Manager 来实现。

4. 增强响应灵命性

一般来说,在应用程序里,100--200ms 是用户能感知阻滞的时间阈值。因此,这里有一些额外的技巧来避免 ANR,并有助于让你的应用程序看起来有响应性。

如果你的应用程序为响应用户输入正在后台工作的话,可以显示工作的进度(ProgressBar 和 ProgressDialog 对这种情况来说很有用)。

5. 如果你的应用程序有一个耗时的初始化过程的话,可以考虑显示一个 SplashScreen(闪屏页)或者快速显示主画面并异步来填充这些信息。在这两种情况下,你都应该显示正在进行的进度,以免用户认为应用程序被冻结了。

总之,主线程尽量只做 UI 相关的操作,避免耗时操作,比如过度复杂的 UI 绘制网络操作文件I/O 操作;避免主线程跟工作线程发送锁的竞争,减少系统耗时 binder 的调用,谨慎使用 sharePreference,注意主线程执行 provider query 操作。尽可能减少主线程的负载,让其空闲待命,以便随时响应用户的操作。

ANR 分析

1. 前台 ANR 发生后,系统会马上去抓取现场的信息,用于调试分析,收集的信息如下:

  \bullet 将 am_anr 信息输出到 EventLog,也就是说 ANR 触发的时间点最接近的就是 EventLog 中输出 am_anr 信息。

  \bullet 收集以下重要进程的各个线程调用栈 trace 信息,保存在 data/anr/traces.txt 文件

        a. 当前发生 ANR 的进程,system_server 进程以及所有 persistent 进程

        b. audioserver, cameraserver, mediaserver, surfaceflinger 等重要的 native 进程

        c. CPU 使用率排名前 5 的进程

  \bullet 将发生 ANR 的 reason 以及 CPU 使用情况信息输出到 main log

  \bullet 将 traces 文件和 CPU 使用情况信息保存到 dropbox,即 data/system/dropbox 目录

  \bullet 对用户可感知的进程则弹出 ANR 对话框告知用户,对用户不可感知的进程发生 ANR 则直接杀掉

2. 分析步骤

  \bullet 定位发生 ANR 的时间点

  \bullet 查看 trace 信息

  \bullet 分析是否有耗时的 message, binder 调用,锁的竞争,CPU 资源的抢占

  \bullet 结合具体的业务场景的上下文来分析

解决 ANR 问题

ANR 问题线上监控

1.  FileObserver: 可以监控某个目录/文件状态是否发生改变,或者有没有在某个目录下创建/删除文件,再或者往某个文件里添加内容。自定义 class extends FileObserver , 然后去监听 /data/anr/ 目录,如果该目录发生了变化,说明肯定是有 ANR 问题产生了。

Android 系统再此基础上封装了一个 FileObserver 类来方便使用 Inotify 机制。FileObserver 是一个抽象类,需要定义子类实现该类的 onEvent 抽象方法,当被监控的文件或者目录发生变更事件时,将回调 FileObserver 的 onEvent() 函数来处理文件或目录的变更事件。

 2. WatchDog : extends Thread, 监控系统有没有死锁的情况

 

 


http://www.niftyadmin.cn/n/293533.html

相关文章

Camtasia 2023新功能添加了新的视觉效果、滤镜和其他重大改进

总部位于密歇根州的 TechSmith 推出了Camtasia 2023,这是其适用于 Mac 和 Windows 的专业屏幕录制和视频编辑工具的重要新版本。 2023 版本侧重于两个特定领域:提供增强的视觉效果和实现各种用户功能请求。 Camtasia 2023 的亮点包括能够在截屏视频中实…

基于ChatGLM-Med与HuaTuo的微调部署

文章目录 ChatGLM-Med推理过程微调过程 HuaTuo配置环境模型下载推理过程微调过程 如何基于领域知识对类ChatGPT模型进行微调,以提升类ChatGPT模型在领域的问答效果? 有下面两个模型,一起来看看微调后的效果如何。 ChatGLM-Med: 基于中文医学知…

【LeetCode】数据结构题解(6)[回文链表]

回文链表 1.题目来源2.题目描述3.解题思路4.代码展示 所属专栏:玩转数据结构题型 博主首页:初阳785 代码托管:chuyang785 感谢大家的支持,您的点赞和关注是对我最大的支持!!! 博主也会更加的努力…

JavaScript实现输入两个数比较两个数的大小,输出个人信息的两个程序代码

以下为实现输入两个数比较两个数的大小,输出个人信息的两个程序代码和运行截图 目录 前言 一、实现输入两个数比较两个数的大小 1.1 运行流程及思想 1.2 代码段 1.3 JavaScript语句代码 1.4 运行截图 二、输出个人信息 2.1 运行流程及思想 2.2 代码段 2.3…

【郭东白架构课 模块二:创造价值】24|节点四:如何减少语义上的分歧?

你好,我是郭东白。上节课我们通过一个篇幅比较长的电商案例,详细展示了为什么在架构活动中会出现语义分歧。同时也描述了,架构师在统一语义这个环节中所要创造的真正价值是什么。即,看到不同角色之间语境的差异,然后通…

Java:获取Stream流

1.Stream流的作用 结合了Lambda表达式&#xff0c;简化集合、数组的操作。 2.Stream流的使用步骤 1.先得到一条Stream流&#xff08;流水线)&#xff0c;并把数据放上去 单列集合&#xff1a;default Stream<E> stream() Collection中的默认方法双列集合&#xff1a;…

TreeMap源码分析,Collections工具类的使用

TreeMap源码分析 代码演示&#xff1a; 源码分析&#xff1a; /*源码分析&#xff1a;1. 构造器. 把传入的实现了 Comparator接口的匿名内部类(对象)&#xff0c;传给给TreeMap的comparator的属性public TreeMap(Comparator<? super K> comparator) {this.comparator …

Java程序设计入门教程--学习目录-带链接(周更)

一、初识Java语言 1.1 Java语言概述 1.2 搭建开发环境 1.3 第一个Java程序 1.4 Java文档注释 二、Java语言基础 2.1 Java程序结构 2.2 基本数据类型 2.3 变量与常量 2.4 数据类型的相互转换 2.5 控制台输入与输出 三、流程控制与数组 3.1 分支结构 3.2 循环结构 …