ANR异常

android ANR 异常的英文全称是 “Application Not Responding”,中文意思即为应用无响应。
在介绍xCrash捕获ANR异常时,先简单介绍一下ANR异常,以及产生ANR异常的原因,以及ANR常用的处理方式。

ANR异常产生的类型

  1. KeyDispatchTimeout。UI主线程对于输入事件,即Inputdispatch事件超过5S没有处理产生ANR。
  2. BroadcastTimeout。在广播接收器BroadcastReceiver的onReceive在一定的时间内没有执行完程序就会发生ANR异常。如果广播接收器所在的进程是前台进程,超时时间为10S;如果广播接收器所在的进程是后台进程,超时时间为60S。
  3. ServiceTimeout。前台的server的各个生命周期函数包括(onCreate,onStart,onBind)在20S内没有处理完成,发生ANR异常。后台的server的各个生命周期函数包括(onCreate,onStart,onBind)在200S内没有处理完成,发生ANR异常。
  4. ContentProviderTimeout。ContentProvider 在10S内没有处理完成发生ANR。

ANR异常产生的原因

  1. 在主线程执行耗时的操作,常见的耗时操作有IO操作,网络访问,大量数据的读写。
  2. 多线程死锁,造成主线程被阻塞。
  3. service binder的连接达到上线无法和和System Server通信
  4. System Server中WatchDog出现ANR
  5. 系统资源已耗尽(管道、CPU、IO)

ANR异常处理。

android系统发生ANR异常是,logcat会输出一条日志,通过日志可以确定,android 发生ANR异常时,会将日志写入/data/anr/traces.txt。因此可以猜想到应用程序可以监控/data/anr/文件是否有写入,即可判断是否发生ANR异常。如何监控文件夹,android提供了一个类“FileObserver”,可以监控文件。但是通过这种方式监控是否发生ANR异常,对android的版本有要求,API版本必须小于21。xCrash对应API版本小于21的也是采用此种方式,腾讯提供的Buly也是采用该种方式。本文章通过对xcrash的源码分析,简要分析一下此种方式监控ANR异常。

12-12 14:51:19.705 19983-19992/com.exam.simple I/art: Wrote stack traces to '/data/anr/traces.txt'

xCrash捕获ANR异常

xCrash是爱奇艺开源的在android平台上面捕获异常的开源库。xCrash能为安卓 APP提供捕获Java崩溃异常,native崩溃异常和ANR异常。

xCrash 能在 App 进程崩溃或 ANR 时,在你指定的目录中生成一个 tombstone 文件(格式与安卓系统的 tombstone 文件类似)。

xCrash项目地址:
github:https://github.com/iqiyi/xCrash
gitee:https://gitee.com/caikelun/xCrash

xCrash捕获ANR异常初始化

xCrash初始化接口,如果不设置参数InitParameters ,采用默认参数,xCrash库默认支持捕获ANR异常。

 public static int init(Context ctx) {return init(ctx, null);}public static synchronized int init(Context ctx, InitParameters params){...// 允许捕获anr异常,且系统版小于21,初始化Anr异常处理器if (params.enableAnrHandler && Build.VERSION.SDK_INT < 21) {AnrHandler.getInstance().initialize(ctx,// context上下文pid,// 进程PIDprocessName,// 进程名appId,params.appVersion,// app应用版本params.logDir,// 日志输出文件夹// 以下为可配置参数params.anrCheckProcessState,params.anrLogcatSystemLines,params.anrLogcatEventsLines,params.anrLogcatMainLines,params.anrDumpFds,params.anrCallback);}}

xCrash 也支持自定义参数来设置监控ANR异常,与ANR异常相关的属性和接口如下。

public final class XCrash {...public static class InitParameters{...//anr// anr异常处理器,默认为true,如果为false不捕获anr异常boolean        enableAnrHandler     = true;//  是否抛出anr异常。默认为trueboolean        anrRethrow           = true;// 是否设置anr的状态标志给进程状态(具体参见源码中的注释)boolean        anrCheckProcessState = true;// anr日志最大保留文件数量int            anrLogCountMax       = 10;// 执行命令 logcat -b system 输出的日志行数 int            anrLogcatSystemLines = 50;// 执行命令 logcat -b event 输出的日志行数 int            anrLogcatEventsLines = 50;// 执行命令 logcat -b maint输出的日志行数 int            anrLogcatMainLines   = 200;// 是否输出app进程的下打开的文件描述符boolean        anrDumpFds           = true;// 发生anr异常的应用回调ICrashCallback anrCallback          = null;}
}

初始化xCrash的ANR异常代码。代码中只展示ANR异常配置

 XCrash.init(this, new XCrash.InitParameters().enableAnrCrashHandler() //开启ANR异常捕获;捕获disableAnrCrashHandler().setAnrCheckProcessState(true) //是否设置anr的状态标志给进程状态.setAnrRethrow(true) // 是否抛出anr异常。默认为true.setAnrLogCountMax(100).setAnrLogcatSystemLines(100).setAnrLogcatEventsLines(100).setAnrLogcatMainLines(100).setAnrDumpFds(true).setAnrCallback(callback)

ANR异常处理器

类AnrHandler即为ANR的异常处理器。AnrHandler 为单例模式源码如下。

class AnrHandler {private static final AnrHandler instance = new AnrHandler();private AnrHandler() {}static AnrHandler getInstance() {return instance;}
}

AnrHandler 的核心代码为initialize函数接口中的FileObserver。源码如下

private FileObserver fileObserver = null;
void initialize(....){// 实例化FileObserver ,监控路径"/data/anr/",监听文件被写入fileObserver = new FileObserver("/data/anr/", CLOSE_WRITE) {public void onEvent(int event, String path) {try {if (path != null) {String filepath = "/data/anr/" + path;// 写入的文件是否有关键字 “trace”if (filepath.contains("trace")) {// 处理anr异常handleAnr(filepath);}}} catch (Exception e) {XCrash.getLogger().e(Util.TAG, "AnrHandler fileObserver onEvent failed", e);}}};try {// 启动FileObserver 监控fileObserver.startWatching();} catch (Exception e) {fileObserver = null;XCrash.getLogger().e(Util.TAG, "AnrHandler fileObserver startWatching failed", e);}
}

FileObserver 简介

这部分参考了博客(博客路径:https://www.robotshell.com/2017/08/30/Android-FileObserver%20%E7%B1%BB%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/)。

android的FileObserver 是抽象类,是基于linux的inotify的特性来实现的,主要用来监控文件系统,根据文件的特定事件发出事件是。
android 官方提供的参考路径:https://developer.android.com/reference/android/os/FileObserver

处理ANR异常

以上代码介绍到anr的处理函数handleAnr(String filepath)。以下为源码

private void handleAnr(String filepath) {...// 读取anr文件 /data/anr/trace*.txt。返回文件内容String trace = getTrace(filepath, anrTime.getTime());//删除其他的anr异常日志文件if (!FileManager.getInstance().maintainAnr()) {return;}//获取  tombstone 的文件头String emergency = null;try {emergency = getEmergency(anrTime, trace);} catch (Exception e) {XCrash.getLogger().e(Util.TAG, "AnrHandler getEmergency failed", e);}// 创建anr异常日志保存文件File logFile = null;try {String logPath = String.format(Locale.US, "%s/%s_%020d_%s__%s%s", logDir, Util.logPrefix, anrTime.getTime() * 1000, appVersion, processName, Util.anrLogSuffix);logFile = FileManager.getInstance().createLogFile(logPath);} catch (Exception e) {XCrash.getLogger().e(Util.TAG, "AnrHandler createLogFile failed", e);}if (logFile != null){// 根据配置将日志文件头,traces,logcat日志保存在文件中。}
}

anrCheckProcessState

源码中有anrCheckProcessState属性。如果属性设置为true则会执行以下代码。

// anr超时时间是15S
private final long anrTimeoutMs = 15 * 1000;
static boolean checkProcessAnrState(Context ctx, long timeoutMs) {ActivityManager am = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);if (am == null) return false;// 获取当前进程的idint pid = android.os.Process.myPid();long poll = timeoutMs / 500;for (int i = 0; i < poll; i++) {//获取系统中所有进程的错误信息List<ActivityManager.ProcessErrorStateInfo> processErrorList = am.getProcessesInErrorState();if (processErrorList != null) {for (ActivityManager.ProcessErrorStateInfo errorStateInfo : processErrorList) {// 进程ID和当前应用ID相同,且错误状态是ANR异常if (errorStateInfo.pid == pid && errorStateInfo.condition == ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING) {return true;}}}try {Thread.sleep(500);} catch (Exception ignored) {}}return false;}

通过以上代码,可以确定该函数的主要功能有:

  1. 过滤掉其他应用的异常。
  2. 过滤掉本应用非ANR异常。
    通过这个函数可以保证anrHandler处理的是当前应用的ANR异常。

总结

以上为xCrash的ANR源码分析,整体较为简单,还请大家不要见笑。

xCrash 捕获ANR异常相关推荐

  1. 关于ANR异常捕获与分析,你所需要知道的一切

    关于ANR异常捕获与分析,你所需要知道的一切 2017年11月27日 19:48:05 大_熊_ 阅读数:1796 标签: AndroidANRAMSBugly 更多 个人分类: Android 应用 ...

  2. 鸿蒙开源第三方组件——ANR异常监测组件 ANR-WatchDog-ohos

    前言 基于安卓平台的消息弹框组件ANR-WatchDog(https://github.com/SalomonBrys/ANR-WatchDog),实现鸿蒙化迁移和重构.代码已经开源到(https:/ ...

  3. WCF客户端不能用在Using语句块中,因为它可能会抛出不可预知的异常。即使你捕获了异常,仍有可能一直保持连接。...

    WCF客户端不能用在Using语句块中,因为它可能会抛出不可预知的异常.即使你捕获了异常,仍有可能一直保持连接.让我们来看看形成这一问题的历史原因,并提出几个补救措施. 在.NET中,资源管理的基础就 ...

  4. winform程序捕获全局异常,对错误信息写入日志并弹窗

    使用场景:在winform程序中如果没对方法进行try catch操作,若方法内出错,则整个程序报错并退出,如下图 如果程序已在客户手中,若没对错误的详细信息进行拍照,我们则不知道错误原因是什么.我们 ...

  5. java try catch嵌套_解析Java中未被捕获的异常以及try语句的嵌套使用

    Java未被捕获的异常 在你学习在程序中处理异常之前,看一看如果你不处理它们会有什么情况发生是很有好处的.下面的小程序包括一个故意导致被零除错误的表达式. class Exc0 { public st ...

  6. python——异常(1),捕获特定异常

    python--异常(1),捕获特定异常 参考文章: (1)python--异常(1),捕获特定异常 (2)https://www.cnblogs.com/kekefu/p/12317986.html ...

  7. PHP 捕获全局异常

    PHP 捕获全局异常 参考文章: (1)PHP 捕获全局异常 (2)https://www.cnblogs.com/yaomao/p/11260388.html (3)https://www.java ...

  8. Java并发-UncaughtExceptionHandler捕获线程异常信息并重新启动线程

    Java并发-UncaughtExceptionHandler捕获线程异常信息并重新启动线程 参考文章: (1)Java并发-UncaughtExceptionHandler捕获线程异常信息并重新启动 ...

  9. C# winform 捕获全局异常

    using System; using System.Collections.Generic; using System.Windows.Forms; using System.IO; namespa ...

最新文章

  1. 数据挖掘导论读书笔记5关联分析的基本概念和算法
  2. 数据库基础 (六)单表查询进阶
  3. [WPF]winfom中ShowWPF新窗口时TextBox等控件无法输入问题解决方法 .
  4. ViewPager 在 ScrollView 中显示不全的解决方法
  5. 当重复调用addsubview时出现显示重叠问题
  6. Termux第一篇之ssh使用
  7. 关于逻辑或的一个小小应用注意点
  8. Win7虚拟Wifi热点(设置后能连接wifi但无法上网的可按后面提示操作)
  9. BUPT复试专题—最小距离查询(2013)
  10. springMVC3学习(十)--注解式控制器
  11. nginx 之 proxy_pass详解
  12. 有界、无界队列对ThreadPoolExcutor执行的影响
  13. 数据库编程之ODBC编程
  14. 杭电acm题库 1001 统计气球问题
  15. cuda历史版本下载
  16. vmware linux top si高以及网卡队列、软负载相关优化
  17. 发起http请求raw格式
  18. java 感想_Java课程感想
  19. mysql 合计 小计_用SQL实现统计报表中的小计与合计的方法详解
  20. error: redefinition of ‘xxx’问题的解决

热门文章

  1. 高超声速飞行器鲁棒控制系统的设计
  2. Codefores 460C-Present(二分+贪心)
  3. 大数据组件——Zookeeper配置文件解析
  4. 学习英文-学以致用【场景:找朋友】
  5. 做题笔记 2019/10/6
  6. C# 防止界面假死 多线程进度条的合理使用
  7. HE4057原厂500mA线性锂离子电池充电器
  8. Redis查询Key
  9. PSP - AlphaFold2 中 Multimer MSA 特征的源码简读 (2)
  10. shell脚本相关总结(1)