热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

一文教你轻松搞定ANR异常捕获与分析方法

1.ANR产生原理关于ANR的触发原因,Android官方开发者文档中“WhatTriggersANR?”有介绍,如下:General

1. ANR 产生原理

关于 ANR 的触发原因,Android 官方开发者文档中 “What Triggers ANR?” 有介绍,如下:

Generally, the system displays an ANR if an application cannot respond to user input. For example, if an application blocks on some I/O operation (frequently a network access) on the UI thread so the system can't process incoming user input events. Or perhaps the app spends too much time building an elaborate in-memory structure or computing the next move in a game on the UI thread. It's always important to make sure these computations are efficient, but even the most efficient code still takes time to run......

即,常见的有如下两种情况会产生 ANR:

输入事件(例如按键或屏幕轻触事件等)在 5 秒内没有响应;

BroadcastReceiver 在 10 秒内没有执行完成。

结合 Android 相关源码分析可知,输入事件的 ANR 检测是基于输入事件本身驱动的,系统要求在 App进程中处理完成每个输入事件后,通知系统进程事件处理完毕,以此判断 App是否无响应。

要产生 ANR,至少得有两个输入事件,场景如下:

第一个输入事件产生,系统将其发送给用户当前操作的 App;

系统收到第二个事件,发现当前距第一个输入事件发送时间超过 0.5s 仍未处理完毕,则设置一个定时器,5s 后触发;

5s 之后,若系统发现第一个输入事件仍然没有回应时,则触发 ANR,激活 App 中的 Signal Cather 线程生成 traces.txt,然后弹出 ANR 对话框,告知用户 App 无响应。

也就是说,要产生 ANR,第一个输入事件必需在 5.5s 以上没有被处理完成并反馈回系统;并且要有第二个输入事件产生。如果没有第二个输入事件,即便第一个输入事件执行了 60s 或更长时间,也是不会产生 ANR 的。

2. ANR 日志生成原理

系统的 system_server 进程在检测到 App 出现 ANR 后,会向出现 ANR 的进程发送 SIGQUIT (signal 3) 信号。正常情况下,系统的 libart.so 会收到该信号,并调用 Java 虚拟机的 dump 方法生成 traces。

以友盟+的 U-APM 应用性能监控平台为例,集成SDK 后,SDK 会拦截 SIGQUIT。在出现 ANR 时,libcrashsdk.so 会优先收到信号,并生成 traces 和 ANR 日志。在 SDK 处理完信号后,会将信号继续传递给系统的 libart.so,让系统生成 ANR traces.txt。

如下图,红色线为 U-APM SDK 处理 ANR 信号和生成 ANR 日志的流程,紫色线为系统生成 ANR traces.txt 的流程。

U-APM SDK ANR 捕获原理

其中,SDK 生成 traces 时,使用的是 libart.so 中的 dump 方法,生成的内容与系统原生的基本一致。并且,U-APM SDK 在调用 dump 方法时进行了优化,dump 速度较系统生成原生 traces 的速度显著提升,有效地避免了可能因生成 traces 时间过长,而被 system_server 使用 SIGKILL (signal 9) 再次强杀。

在获取所有线程的 traces 信息后,生成完整的 ANR 日志,还会提供获取触发 ANR 的原因、手机中 TOP 进程 CPU 使用率、ANR 进程中 TOP 线程 CPU 使用率、CPU 各核心处理时间分布情况、磁盘 IO 操作等待时长等重要信息。

目前,SDK 生成的 ANR 日志信息,基本包含系统生成的 ANR 日志的所有内容,甚至还包含一些系统日志中没有的内容,以及 App增加的自身的业务相关信息,对分析、定位和解决 ANR 问题,提供了更加强有力的支撑。

3、日志分析

如开发者接入了SDK,ANR 日志将自动启用,出现 ANR 时,会先于系统生成 ANR 日志。日志的主要内容介绍如下:

1)ANR 日志结构

使用日志分析插件,我们可以清晰地看到 生成的 ANR 日志包含的内容以及重点信息,如下:

ANR 日志结构

除了生成的日志以 Section 分为多个部分,其中,包含重要信息的 Section 会使用红色标出,特别重要的信息还会加粗。另外,每个 Section 有快捷键可直接跳转到相应位置。

2)ANR 概要

概要信息如下:

ANR 概要信息

这部分内容主要从系统获取,其包含了 ANR 的进程名、ANR 产生的时间、ANR 的原因、ANR 前后几秒内系统 TOP 进程的 CPU 使用率等。其中,通过 ANR 原因可以得知是输入事件处理超时,还是 BroadcastReceiver 等其它消息处理时间过长;通过 CPU 使用率则可以得知是哪个进程占用 CPU 资源过多。

3)系统资源使用情况

可记录在出现 ANR 前一段时间内,CPU 平均使用率、CPU 各核心使用率及其耗时分布,ANR 进程中 TOP 线程的执行耗时及比例、出现页错误的次数,磁盘 IO 操作等待时长及次数等内容。如下:

系统资源使用情况

当 IO 繁忙导致 ANR 时,io wait time 和 CPU 时间分布中的 iowait 比例会比较突出;通过 CPU 时间分布中的 user 和 system 占比,则可以知道是用户态代码执行耗时过长,还是 Linux 内核的系统调用耗时太久。

4)ANR traces

traces 信息是 ANR 日志中最关键的内容。如U-APM生成的 traces 信息包含了出现 ANR 时主线程的 native 调用栈和所有线程的 java 调用栈。通常死锁问题通过调用栈中的信息可以很容易发现。

ANR traces

U-APM SDK 的 traces 由 fork 的子进程生成,不会因 Java 虚拟机出现 BUG 导致生成 traces 时又出现 native 崩溃,也不会因 dump 时卡死阻塞整个 ANR 日志的生成。

5)Logcat

以U-APM为例,会在 ANR 时抓取 Android logcat。APM SDK 能绕开部分 ROM 增加的权限控制,拿到当前 App ANR 前相关的 log 信息。当前进程以及当前错误线程输出的 log 会被重点标出,error 和 warning 也会以显目的颜色标出。

logcat

6)内存等其它信息

通过ANR日志可以分析出一系列的内存信息,如:

系统的 RAM 总内存、剩余可用内存;

当前进程占用的虚拟内存、物理内存;

Java 占用的总内存和可用内存;

Native 占用的内存和可用内存等。

另外,ANR 日志同 Java 和 Native 崩溃日志一样,支持业务自定义日志内容扩展,如:

崩溃前增加简短的自定义头信息;

崩溃前注册外部文件,崩溃时其内容将被带入日志;

崩溃前缓存业务相关的最近若干条操作或信息;

崩溃时通过回调返回业务最新内容等。

4、ANR监控工具

选择一款有超强捕获能力的专业产品,对于开发者定位和修复稳定性问题至关重要。友盟+U-APM SDK集成了UC 内核团队强大的技术及友盟+超强的错误捕获能力,通过数万次捕获实践中积累了丰富经验,在产品、性能和研发能力上都极大保障了开发者定位和修复稳定性问题的超强效率。

 

原文链接

本文为阿里云原创内容,未经允许不得转载。


推荐阅读
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 在Java中,我会做这样的事情:classPerson{privateRecordrecord;publicStringname(){record().get(name);}p ... [详细]
  • 本文由编程笔记小编整理,主要介绍了使用Junit和黄瓜进行自动化测试中步骤缺失的问题。文章首先介绍了使用cucumber和Junit创建Runner类的代码,然后详细说明了黄瓜功能中的步骤和Steps类的实现。本文对于需要使用Junit和黄瓜进行自动化测试的开发者具有一定的参考价值。摘要长度:187字。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
  • 本文介绍了Java集合库的使用方法,包括如何方便地重复使用集合以及下溯造型的应用。通过使用集合库,可以方便地取用各种集合,并将其插入到自己的程序中。为了使集合能够重复使用,Java提供了一种通用类型,即Object类型。通过添加指向集合的对象句柄,可以实现对集合的重复使用。然而,由于集合只能容纳Object类型,当向集合中添加对象句柄时,会丢失其身份或标识信息。为了恢复其本来面貌,可以使用下溯造型。本文还介绍了Java 1.2集合库的特点和优势。 ... [详细]
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
author-avatar
瓶子2502854683
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有