Android ANR产生的原因以及解决方式

一、什么是ANR

ANR是Android系统中的一种错误状态,全称为Application Not Responding,中文翻译为“应用无响应”。当Android系统检测到应用程序在一段时间内未能响应用户输入或无法执行主要的UI线程操作时,就会触发ANR错误。ANR是一种系统保护机制,旨在确保应用的响应性,防止用户在使用应用时遇到卡顿或无响应的情况。

二、ANR的分类

超时时间都是在AMS中定义的

ANR类型解释超时时间
InputDispatching Timeout按键或触摸事件在特定时间内无响应5秒
Broadcast TimeoutBroadcastReceiver的onReceive方法在特定时间内无法处理完成。前台广播在Android8.0之前10秒8.0之后15秒,后台广播60秒
Service TimeoutService在特定的时间内生命周期函数无法处理完成前台服务20秒后台服务200秒
ContentProvider TimeoutContentProvider在特定的时间内没有完成发布10秒

三、产生ANR的原因

主线程阻塞: 当应用在主线程执行耗时操作时,例如网络请求或复杂计算I/O操作,会导致主线程无法及时响应用户输入,触发ANR。

死锁: 多线程编程中,死锁可能发生,当一个线程等待另一个线程释放锁时,应用就会无法继续执行,导致ANR。

非法耗时操作: Android规定在主线程中不允许执行耗时操作,违反这一规定会触发ANR。

**同步Binder调用:**主线程在对另一个进程进行同步Binder调用,而后者需要很长时间才能返回。(如果我们知道调用远程方法需要很长时间,我们应该避免在主线程调用)

关于上述ANR的分析定位参照:Android造成ANR的常见原因及示例分析 - 简书 (jianshu.com)

四、上线后的App如何检测ANR

1.ANR WatchDog

既然 ANR 的原因是输入在定时间内没有响应,那么我们很自然地想到,向主线程发送一个任务,如果一段时间内没有被执行的话,就认为发生了 ANR

这个思路主要有以下几个问题

  1. 不准确,超时条件不一定会导致 ANR,例如,5 秒超时只是在 TouchEvent 未被消耗时发生 ANR 的条件之一,而其他条件则不一定是 5 秒。
  2. 漏检测:如果超时时间定为 5 秒,去检测 TouchEvent 的 ANR 存在一定的漏检测的概率(周期不同步。

2.信号监听思路

在上面介绍 ANR 总体流程时,我们注意到当 ANR 发生时会发送 SIGQUIT(通常为信号3)信号,那么我们通过监听这一信号不就可以实现 ANR 监控了吗?事实上 XCrashMatrix 都是通过这种方式实现 ANR 监控的

在这里需要注意,默认情况下进程通过SignalCatcher监听SIGQUIT信号,进行堆栈转储生成 ANR Trace 文件。因此当我们监听SIGQUIT信号后,需要重新向SignalCatcher发送SIGQUIT

如果缺少重新向 SignalCatcher 发送 SIGQUIT 信号的步骤,Android System 管理服务(AMS)将一直等待 ANR 进程写入堆栈信息。直到超过20秒的超时时间,AMS 才会被迫中断,并继续后续流程。这将导致 ANR 弹窗的显示非常缓慢(因为超时时间为20秒),同时在 /data/anr 目录下也无法生成完整的 ANR Trace 文件。

这个思路主要有下面几个问题

当监听到 SIGQUIT 信号时,不一定是发生了 ANR。

Matrix 的文档中提到了两种误报的情况:

  1. 比如可能是其它进程 ANR 了,发生 ANR 的进程不是唯一需要进行堆栈转储的进程。系统会收集许多其他进程进行堆栈转储,用于生成 ANR Trace 文件
  2. 厂商或者是开发者自己发送的SIGQUIT信号,发送SIGQUIT信号其实是很容易的一件事情

因此我们需要在监听到信号时再进行一次检查:在 ANR 弹窗前,会给发生 ANR 的进程标记一个 NOT_RESPONDING 的 flag,而这个 flag 我们可以通过 ActivityManager 来获取

漏报情况处理

当进程被标记为 NOT_RESPONDING 时一定发生了 ANR,但是当进程发生了 ANR 时,不一定会被标记为 NOT_RESPONDING

Matrix 的文档中提到了两种漏报情况

  1. 后台ANR(SilentAnr): 后台 ANR 会直接杀死进程,不会走到标记状态的代码
  2. 厂商定制逻辑: 相当一部分机型(比如 OPPO、VIVO 两家的高版本 Android )修改了 ANR 的逻辑,即使是前台 ANR 也会直接杀死进程

Matrix 通过判断主线程在收到 SIGQUIT 信号时是否处于卡顿状态来判断当前是否发生 ANR

问题:

2 sp为什么会导致ANR

4项目上线后如何检测ANR(handle watchDog,信号机制)

参考连接:https://juejin.cn/post/7314135212355092491

https://juejin.cn/post/7229370243146727484

  • 26
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值