Android ANR机制的原理以及问题分析(一)

一、前言

Android开发人员对ANR应该毫不陌生——Application Not Responding,即应用程序未响应。ANR的核心原理是消息机制的调度和超时处理,它要求主线程在限定时间内做完任务处理,比如:启动Activity/Service、发送广播、ContentProvider查询、Input事件分发等,否则就可能发生ANR引起性能问题。处理超时时,系统会认为当前主线程已经失去响应其他操作的能力。这些耗时操作包括:密集的CPU运算、大量的IO操作、复杂的media编解码、大量需要绘制的嵌套布局等等,这些都可能会降低主线程的响应能力。

PS:会有相当一部分的ANR问题是很难分析的,有时候由于系统底层的一些影响,导致消息调度失败,出现问题的场景难以复现。这类ANR问题往往需要花费大量的时间取了解系统的一些行为,除了了解ANR机制本身外,还需要对系统子功能模块的具体实现进行分析。

二、 ANR的类型

ANR大致可以分为以下四种类型:

  • Service Timeout(Timeout executing service:)

前台服务20s内未执行完成
后台服务200s内未执行完成

  • Broadcase Timeout(Timeout of broadcase:)

前台广播在10s内未执行完成
后台广播在60s内为执行完成

  • ContentProvider Timeout(Timeout publishing content providers:)

ContentProvider超时,这里分为两种情况:
【1】 publish时超过CONTENT_PROVIDER_PUBLISH_TIMEOUT 10s的时间,触发timeout publishing content providers,会直接kill,这一类的启动超时,有service,process,同样会触发.
【2】 对给定的provider进行操作时,如果通过setDetectNotResponding方法给定了超时时间,例如query时超过设定的时间会触发ANR

三、臭名昭著的ANR

在这里插入图片描述
我们遇到的ANR大部分都会出现类似上面的对话框,伴随着ANR的日志同步出现、分析一些初级的ANR问题,只需要简单看看输出的日志即可,但对于一些由系统原因(比如CPU负载过高、进程死锁)引发的ANR,就需要熟悉整个ANR机制,才有可能定位出问题的原因。

首先,通过查看log日志中的ANR in关键字找到AppErrors.java中appNotResponding()负责弹出上面这个ANR对话框。这个类核心功能就是负责显示ANR的对话框还有出现crash时出现的ForceClose对话框

appNotResponding具体代码逻辑如下:

  1. 如果有设置IActivityController的话,通知client端appEarlyNotResponding
  2. 检测是香是下面几种情况的ANR.如果是直接忽路
  3. 记录ANR出现时的1og.方便后面调试问题

如果没有生成对应的trace文件直接发送SIGNALQUIT命令,也就是kill-3

  1. 添加日志到Dropbox
  2. 通过Handler发送Message给AMS,通知运行在UiThread的UiHandler,显示ANR对话框
//frameworks/base/services/core/java/com/android/server/am/AppErrors.java

final void appNotResponding(ProcessRecord app, ActivityRecord activity,
        ActivityRecord parent, boolean aboveSystem, final String annotation) {
   
    ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
    SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);

    //【1】如果有设置IActivityController的话,通知client端appEarlyNotResponding
    if (mService.mController != null) {
   
        try {
   
            // 0 == continue, -1 = kill process immediately
            int res = mService.mController.appEarlyNotResponding(
                    app.processName, app.pid, annotation);
            if (res < 0 && app.pid != MY_PID) {
   
                app.kill("anr", true);
            }
        } catch (RemoteException e) {
   
            mService.mController = null;
            Watchdog.getInstance().setActivityController(null);
        }
    }
    //...省略
    synchronized (mService) {
   
        //【2】检测是否是下面几种情况的ANR,如果是直接返回
        // A:正在关机 B:已经出现了ANR的应用 C:已经崩溃的应用 D:AM杀死的应用 E:已经死亡的应用
        // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
        if (mService.mShuttingDown) {
   
            Slog.i(TAG, "During shutdown skipping ANR: " + app + " " +<
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值