ANR分析

2018-08-15  本文已影响15人  azmohan

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

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
上一篇下一篇

猜你喜欢

热点阅读