我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android ANR分析trace文件的产生流程详情

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android ANR分析trace文件的产生流程详情

前言

首先收集需要dump trace的进程并给对应进程发送dump trace的信号

1.当一些带有超时机制的系统消息(如:Service的创建)判定超时后,会调用系统服务AMS接口,收集ANR相关信息并存档(data/anr/trace, data/system/dropbox)

2.进入到AMS中,AppError会先进行筛选(1.当前进程正在进行dump流程 2.已经发生crash 3. 已经被系统kill 4.系统是否正在关机等情况),如果都不符合,则认为当前进程发生了anr。

3.接下来系统在判断当前ANR进程对用户是否可感知,然后开始统计与该进程由关联的进程,或者一些系统核心服务进程的信息(例如与应用交互的SurfaceFligner,System Server等系统进程),如果这些系统服务进程在响应时被阻塞,那么将导致应用进程IPC通信过程被卡死。接着获取其他系统核心进程,因为这些服务进程是init进程直接创建的,并不在SystemServer或Zygote进程管理范围。 >firstPids队列:第一个是ANR进程,第二个是system_server,剩余是所有persistent进程; Native队列:是指/system/bin/目录的mediaserver,sdcard 以及surfaceflinger进程; lastPids队列: 是指mLruProcesses中的不属于firstPids的所有进程。

4.在收集完第一步信息后,接下来便开始统计各进程本地的更多信息,如虚拟机信息,java线程状态及堆栈。首先会弹出一个ANR的对话框,然后向UI线程发送SHOW_NOT_RESPONDING_MSG消息

5.当UI线程收到该消息后,会调用dumpStackTraces函数:

最重要的一点:向目标进程发送SINAL_QUIT(进程中的Signal Catcher会进行阻塞检测收集信息后面讲),firstPids列表中的进程, 两个进程之间会休眠200ms, 可见persistent进程越多,则时间越长. top 5进程的traces过程中, 同样是间隔200ms, 另外进程使用情况的收集也是比较耗时.

总结;

>将am_anr信息输出到EventLog(分析anr问题时先看该log) 获取重要进程的信息,java进程的,和native的进程 将ANR的Reason和CPU使用的情况输出到main_log 在将CPU使用情况和进程的trace文件信息,在保存到drpobox文件下 向收集到的进程发送SINAL_QUIT信号。

接着分析最后一步向收集到的进程发送信号

(Android5.0之前是dump用的SuspendAll线程,收集信息之后用ResumeAll恢复。在5.0之后采用的是checkPoint进行dump信息)

发生ANR时,systemServer进程会执行dumpStackTraces函数,在该函数中发SIGQUIT信号给对应的进程(上面有分析到) 处于安全考虑,进程之间是相互隔离的,即使系统进程也无法获取其他进程的信息,所以要借助于IPC通信,将指令发送到目标进程,目标进程接收到消息后,协助完成自身进程Dump信息并发送给系统进程。Android P 流程:

1.一个进程接收到了SIGQIUT信号的时候,SingaCatcher线程的WaitForSignal函数会返回接着会调用到HandlerSigQuit()函数。

2.hindleSigQuit()函数为:

3.DumpForSigQuit()函数:

这是读取的信息,但是什么时候去读取呢(什么时候才能保证获取到的却是是需要的东西,例如GC信息,当前分配了多少对象,这些打印一般都需要在suspend当前进程里面的所有的线程),接下来先分析这个suspend过程:

这个挂起SupendAll实在Thread_list.cc中实现的,他的作用就是用来suspend当前进程里面所有其他的线程(一般发生在GC,DumpForSigQuit等过程中)。SuspendAll过程实现最重要的就是ModifySupendCount(self,+1,false)这段语句他会修改对应Thread对象的suspend引用计数:

因为传入的delta值是+1所以会先执行AtmoicSetFlag()利用原子操作设置了KSuspendRequest标志位,代表当前这个线程有挂起请求。什么时候会进行检测这个标志位呢?这里涉及到了checkPoint的知识点最后讲解(在线程运行中进行上下文切换(例如java线程转换为Native线程)时就会运行CheckSuspend函数,这个函数才是真正的把当前线程suspend:

可以看到检测到了KSuspendRequest标记就会执行FullSuspend函数,KSuspendRequest标志位是用来dump线程的堆栈的,分析完了SuspendAll之后,再继续分析FullSuspendCheck函数:

调用TransitionFromRunnableToSuspend()这个函数后,线程就进入了KSuspended状态,然后在调用TransitionFromSuspendedToRunnablecpm函数从Suspend状态切换到Runnable状态的时候会阻塞在一个条件变量上,除非调用SuspendAll的线程接着又调用了ResumeAll()函数,要不然这些线程就会一直被阻塞住。 4.现在就把SuspendAll的流程分析完了,但是dump线程堆栈的时候并不是在设置了挂起标志位(KSuspendRequest)后执行的,与他相关的是另外一个标志位KCheckpointRequest,接下来看一下Thread_list的Dump函数,这个函数会在Thread_list的DumpForSigQuit中会被调用到,也就是在Signal Cathcer线程处理SIGQUIT信号的过程中。

这个函数先创建了一个叫DumpCheckPoint对象checkpoint,然后调用了RunCheckpoint将这个对象传入,这个函数会返回现在处于Runnable状态的线程个数,接着 调用了WaitForThreadsToRunThroughCheckpoint()等待这些处于Runnable的线程都执行完DumpCheckpoint的Run函数,如果等待超时就会报错。

接着分析RunCheckPoint函数,先看前一部分:

对于处于Runnable状态的线程执行它的RequestCheckpoint函数会返回true,其他状态的线程则会返回false。对于这些非Runnable状态的线程就会像SuspendAll一样会设置KSuspendRequest标志位,后面状态切换的时候就会检查这个标志位挂起。同事RunCheckPoint函数会把这些线程统计到suspend_count_modified_threads这个Vector变量中,在这个变量中的线程,Singal Catcher线程会主动触发他们的dump堆栈过程。接下来再看看这个RequestCheckpoint函数

最后一行设置kCheckpointRequest标志位,在刚才线程切换运行状态时会执行CheckSuspend函数在检测kCheckpointRequest标志位的时候会执行RunCheckpointFunction函数,接着会执行这个checkpoints里面元素的run函数:

(这个存储的其实就是Thread中的RequestCheckpoint在这里不仅设置了标志位还把参数设置为元素的值,这个参数就是Dump里面调用RunCheckpoint传过来的,其实就是DumpCheckpoint)。 ,所以也就是执行DumpCheckpoint的run函数:

其实就是调用了Thread的Dump函数,线程的java堆栈,Native堆栈和Kernel堆栈就是在这里打印的,刚才说对于处于Runnable状态的线程是通过调用他们的RequestCkeckPoint函数,然后它们自己去dump当前堆栈的,而那些不处于Runnable状态的线程则是添加到了一个Vector的变量中,接着就分析RunCheckPoint函数的第二部分:

对于这些不是Runnable状态的线程,他们可能不会主动去调用Run函数,所以只能有Signal Catcher线程去帮他们Dump,至于DumpCheckpoint的Run函数的功能和Runnable状态的线程是一样的,都是打印线程堆栈,并且最后修改引用计数让这些线程在切换状态时继续运行。

总结:

>1.SingalCatcher线程接收到信号后,首先Dump当前虚拟机有关信息(内存状态。对象,加载class,GC等相关信息) 2.接下来会设置每个线程的标记为(check_point),和请求线程状态(suspend)。当线程运行过程中进行上下文切换时,会检查该标记。如果发现有挂起请求,会将自己主动挂起。等到所有线程都挂起之后,SingalCatcher线程开始遍历Dump各个线程的堆栈和线程数据后再唤醒线程。如果某个线程一直无法挂起导致超时,那么本次Dump流程失败抛出异常.

大致流程(Android5.0之前):

checkPoint:

先讲解safePoint,对于ART编译的代码,可以定期轮询当前Runtime来确认是否需要执行某些特定代码;可以认为这些轮询时的点,就是safepoint;safepoint可以用来实现暂定一个java线程,也可以用来实现Checkpoint机制; 例: 当正在执行java代码的线程A执行到safepoint时,会执行CheckSuspend函数,在发现当前线程有 checkpoint request时, 会在这个点执行线程的CheckPoint函数;如果发现当前线程有suspend request时,会进行SuspendCheck,使得线程进入Suspend状态(暂停); 所以说,ART CheckPoint应该是safepoint的一个功能实现;

到此这篇关于Android ANR分析trace文件的产生流程详情的文章就介绍到这了,更多相关Android ANR分析 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android ANR分析trace文件的产生流程详情

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么使用Android ANR分析trace文件的产生流程

这篇文章主要介绍“怎么使用Android ANR分析trace文件的产生流程”,在日常操作中,相信很多人在怎么使用Android ANR分析trace文件的产生流程问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答
2023-07-02

通过Android trace文件分析死锁ANR实例过程

对于从事Android开发的人来说,遇到ANR(Application Not Responding)是比较常见的问题。一般情况下,如果有ANR发生,系统都会在/data/anr/目录下生成trace文件,通过分析trace文件,可以定位产
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录