service的ANR异常源码分析

本文详细分析了Android中ANR(Application Not Responding)异常的原理,包括概念、表现、监测机制和报告机制。重点讨论了Service超时导致的ANR,解释了如何通过监测Service的生命周期来防止ANR,并介绍了ANR报告时的日志类型和分析方法。
摘要由CSDN通过智能技术生成

1.概念

首先,ANR(Application Not responding)是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。ANR由消息处理机制保证,Android在系统层实现了一套精密的机制来发现ANR,核心原理是消息调度和超时处理。

2.表现

当发生ANR时,会收集一些系统状态,譬如CPU/IO使用情况、进程函数调用栈,并且报告用户有进程无响应了(ANR对话框)。
发生ANR时会调用AppNotRespondingDialog.show()方法弹出对话框提示用户,该对话框的依次调用关系如下图所示:
在这里插入图片描述
AppErrors.appNotResponding(),该方法是最终弹出ANR对话框的唯一入口,调用该方法的场景才会有ANR提示,也可以认为在主线程中执行无论再耗时的任务,只要最终不调用该方法,都不会有ANR提示,也不会有ANR相关日志及报告;通过调用关系可以看出哪些场景会导致ANR,有以下四种场景:
(1)Service Timeout:Service在特定的时间内无法处理完成
(2)BroadcastQueue Timeout:BroadcastReceiver在特定时间内无法处理完成
(3)ContentProvider Timeout:内容提供者执行超时
(4)inputDispatching Timeout: 按键或触摸事件在特定时间内无响应。

ANR机制

ANR机制可以分为两部分:
ANR监测机制:Android对于不同的ANR类型(Broadcast, Service, InputEvent)都有一套监测机制。
ANR报告机制:在监测到ANR以后,需要显示ANR对话框、输出日志(发生ANR时的进程函数调用栈、CPU使用情况等)。

举例Service超时监测机制

Service运行在应用程序的主线程,如果Service的执行时间超过20秒,则会引发ANR。

当发生Service ANR时,一般可以先排查一下在Service的生命周期函数中(onCreate(), onStartCommand()等)有没有做耗时的操作,譬如复杂的运算、IO操作等。 如果应用程序的代码逻辑查不出问题,就需要深入检查当前系统的状态:CPU的使用情况、系统服务的状态等,判断当时发生ANR进程是否受到系统运行异常的影响。

如何检测Service超时呢?Android是通过设置定时消息实现的。
Service超时监测机制可以从Service启动流程中找到。
(1)ActiveServices.realStartServiceLocked()主要工作有

private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
   
        ...
        // 主要是为了设置ANR超时,可以看出在正式启动Service之前开始ANR监测;
        bumpServiceExecutingLocked(r, execInFg, "create");
       // 启动过程调用scheduleCreateService方法,最终会调用Service.onCreate方法;
        app.thread.scheduleCreateService(r, r.serviceInfo,
        // 绑定过程中,这个方法中会调用app.thread.scheduleBindService方法
        requestServiceBindingsLocked(r, execInFg);
        // 调动Service的其他方法,如onStartCommand,也是IPC通讯
        sendServiceArgsLocked(r, execInFg, true);
    }

2)bumpServiceExecutingLocked()会调scheduleServiceTimeoutLocked()方法

void scheduleServiceTimeoutLocked(ProcessRecord proc) {
   
        if (proc.executingServices.size() == 0 || proc.thread == null) {
   
            return;
        }
        Message msg = mAm.mHandler.obtainMessage(
                ActivityManagerService.SERVICE_TIMEOUT_MSG);
        msg.obj = proc;
        // 在serviceDoneExecutingLocked中会remove该SERVICE_TIMEOUT_MSG消息,
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值