ANR分析

作者: azmohan | 来源:发表于2018-08-15 16:47 被阅读15次

    Android ANR机制介绍

    ANR(Application Not responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。一般地,这时往往会弹出一个提示框,告知用户当前xxx未响应,用户可选择继续等待或者Force Close。

    Android为什么要引入ANR

    android ui 被设计成非线程安全的(个人认为主要是为了简单),这就要求满足两点:

    1. 不能在非ui线程中操作ui.
    2. 不能阻塞ui线程。

    其中第二个就为ANR埋下了伏笔,既然不能阻塞ui线程,那么如果阻塞了,用户会得到什么交互呢,这就是ANR.告知用户应用程序发生了阻塞ui线程的操作,但是方式简单粗暴,继续等待或者Force Close。其实体验一点不好。这也就对我们程序员有了更高的要求,杜绝黄赌毒,杜绝ANR.

    发生ANR场景

    1. Service Timeout : 服务前台在20s,后台10s内未执行完成。
    2. BroadcastQueue Timeout : 广播前台10s,后台60s内未执行完成。
    3. ContentProvider Timeout : 内容提供器10s未执行完成。
    4. InputDispatching Timeout: 输入事件分发超时,5s。 包含按键与触屏。
     // 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; // 后台
    
    
    
     // How long we allow a receiver to run before giving up on it.
        static final int BROADCAST_FG_TIMEOUT = 10*1000;  // 前台
        static final int BROADCAST_BG_TIMEOUT = 60*1000;  // 后台
    
    
    // How long we wait until we timeout on key dispatching.
        static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
    
    
    // How long we wait for an attached process to publish its content providers
        // before we decide it must be hung.
        static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;
    
    

    注意:
    android的四大组件默认都在主线程中运行的,特别提醒,Service和Broadcast组件也是在主线程中运行的。不要以为Service是在后台运行的,就不在主线程运行。Android提IntentService可以不在主线程执行任务,看源码就会发现其实关联一个HandlerThread.
    顺便说一下,Handler默认也是在主线程中运行的,持有的main thread的looper.如果让handler不在主线程执行,需要绑定其它线程的looper.

    ANR处理

    1. java层的处理:
      所有的java进程都运行在java虚拟机中,当应用发生ANR时,其最终的一个环节是向目标进程通过kill - 3,发送信号SIGNAL_QUIT.Android进程收到SIGQUIT时,虚拟机会捕获这个信号,并输出相应的traces信息,保存到/data/anr/traces.txt中。

    2. native层的处理:
      native进程在发生ANR时,debuggerd服务接收到系统发来的DEBUGGER_ACTION_DUMP_BACKTRACE命令,最后通过dump_backtrace()将日志输出到/data/anr/traces.txt。

    CPU和内存的关键指标含义

    CPU的使用时间:读取/proc/stat

    • user: 用户进程的cpu使用时间
    • nice: 降低过优先级进程的cpu的使用时间,linux进程都是有优先级的,这个优先级可以进行动态调整,譬如进程初始化优先级的值设为10,运行时降低为8,那么修正值为-2就是nice.android系统将user和nice这两个时间归类成user.
    • sys : 内核进程的cpu使用时间
    • idle: cpu等待IO的时间
    • hw irq : 硬件中断的时间,如果外设出现故障,需要通过硬件终端通知CPU保存现场,发生上下文切换时间就是CPU的硬件中断时间。
    • sw irq: 软件中断的时间,同硬件中断一样,如果软件要求CPU中断,同上下文切换时间就是CPU的软件中断时间。

    CPU负载:读取/proc/loadavg

    统计最近1分钟、5分钟、15分钟内cpu的平均活动进程数。CPU的负载就是要处理的任务数。

    手机内存:读取/proc/meminfo

    dumpsys meminfo命令的输出结果分以下4部分:

    序列 类型 排序 解释
    1 process PSS 以进程的PSS从大到小依次排序显示,每行显示一个进程
    2 oom adj PSS Native/System/Persistent/Foreground/Visible/Perceptible/A Services/Home/B Services/Cached,分别显示每类的进程情况;一般而言,占用内存越多,oom_adj就越大,也就越有可能被选中。OOM异常的时候会根据这个表单从下往上杀掉进程释放内存
    3 category PSS 以Dalvik/Native/.art mmap/.dex map等划分的各类进程的总PSS情况
    4 total 总内存、剩余内存、可用内存、其他内存
    root@phone:/ # cat /proc/meminfo
    MemTotal:         883248 kB   //RAM可用的总大小 (即物理总内存减去系统预留和内核二进制代码大小)
    MemFree:           62136 kB   //RAM未使用的大小
    MemAvailable:     192336 kB   
    Buffers:            1648 kB   //用于文件缓冲
    Cached:           175404 kB   //用于高速缓存
    SwapCached:         5392 kB   //用于swap缓存
    
    

    对于cache和buffer也是系统可以使用的内存。所以系统当前总的可用内存为 MemFree+Buffers+Cached。

    技术分析

    image.png

    相关文章

      网友评论

          本文标题:ANR分析

          本文链接:https://www.haomeiwen.com/subject/vakwbftx.html