Android ANR的trace文件基本信息解读

本文详细介绍了如何获取Android ANR的trace文件,以及如何解析线程基本信息、线程状态和堆栈信息。通过对Blocked、Native、Waiting、Sleeping等状态的分析,揭示了导致ANR的各种原因,如锁等待、JNI调用、线程挂起、内存管理问题等,并给出了相应的优化建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ANR堆栈文件的抓取

  • android6以下可以直接读取/data/anr目录下的trace.txt文件,然后过滤出自己进程的anr文件即可
  • android6及以上,没有读取/data/anr的权限,需要native层通过拦截SIGQUIT信号,结合消息机制msg的when超时时间,底层dump堆栈信息。详细原理详见微信技术团队的分享:微信Android客户端的ANR监控方案

Android ANR的trace文件基本信息解读

  • 示例
"main" prio=5 tid=1 Native
  | group="main" sCount=0 dsCount=0 flags=0 obj=0x727c02f8 self=0xb400007a2f210800
  | sysTid=339 nice=-10 cgrp=default sched=0/0 handle=0x7ab698d500
  | state=? schedstat=( 0 0 0 ) utm=0 stm=0 core=0 HZ=100
  | stack=0x7fc8197000-0x7fc8199000 stackSize=8192KB
  | held mutexes=
  at android.os.MessageQueue.nativePollOnce(Native method)
  at android.os.MessageQueue.next(MessageQueue.java:339)
  at android.os.Looper.loop(Looper.java:200)
  at android.app.ActivityThread.main(ActivityThread.java:8312)
  at java.lang.reflect.Method.invoke(Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1049)
线程基本信息
  • 线程优先级:prio=5 (主线程均是5)
  • 线程ID: tid=1 主线程的id一般都是1
  • 线程状态:Native :表示正在调用JNI
    • 还有其他多种状态,表示发生ANR时主线程的状态
  • 线程组名称:group=“main”
  • 线程被挂起的次数:sCount=0
    • 在等待GC时,有时候挂起的线程数量比较多
  • 线程被调试器挂起的次数:dsCount=0
  • 线程的java的对象地址:obj= 0x7682ab30
  • 线程本身的Native对象地址:self=0x7bd3815c00线程调度信息:
线程优先级信息
  • Linux系统中内核线程ID: sysTid=6317与主线程的进程号相同
  • 线程调度优先级:nice=-10
  • 线程调度组:cgrp=default
  • 线程调度策略和优先级:sched=0/0
  • 线程处理函数地址:handle= 0x7c59fc8548
线程状态信息
  • 线程调度状态:state=S
  • 线程在CPU中的执行时间、线程等待时间、线程执行的时间片长度:schedstat=(1009468742 32888019 224)
  • 线程在用户态中的调度时间值:utm=91
  • 线程在内核态中的调度时间值:stm=9
  • 最后执行这个线程的CPU核序号:core=4
线程堆栈信息
  • 堆栈地址和大小:stack=0x7ff27e1000-0x7ff27e3000 stackSize=8MB

ANR中的主线程状态及ANR示例分析

Blocked
  • case 1
"main" prio=5 tid=1 Blocked
  | group="main" sCount=0 dsCount=0 flags=0 obj=0x72996758 self=0xb400007ac7e10800
  | sysTid=28366 nice=-10 cgrp=default sched=0/0 handle=0x7b4f71b500
  | state=? schedstat=( 0 0 0 ) utm=0 stm=0 core=0 HZ=100
  | stack=0x7fe0a67000-0x7fe0a69000 stackSize=8192KB
  | held mutexes=
  at com.autonavi.base.ae.gmap.GLMapEngine.addGestureMessage(SourceFile:-1)
  - waiting to lock <0x0f62c521> (a com.autonavi.base.ae.gmap.GLMapEngine) held by thread 96
  at com.amap.api.mapcore.util.c.addGestureMapMessage(SourceFile:2892)
  at com.amap.api.mapcore.util.p$c.b(SourceFile:801)
  at com.amap.api.mapcore.util.am.a(SourceFile:104)
  at com.amap.api.mapcore.util.ak.d(SourceFile:61)
  at com.amap.api.mapcore.util.p.a(SourceFile:195)
  at com.amap.api.mapcore.util.c.onTouchEvent(SourceFile:1795)
  at com.amap.api.mapcore.util.e.onTouchEvent(SourceFile:47)
  • 分析:
    • GLMapEngine锁被线程96持有,主线程一直等待到ANR,需要解决锁等待的问题
  • case 2
"main" prio=5 tid=1 Blocked
  | group="main" sCount=1 dsCount=0 cgrp=apps/bg_non_interactive handle=0xb6f4fb4c
  | sysTid=4232 nice=0 sched=0/0 cgrp=apps/bg_non_interactive handle=0xb6f4fb4c
  | state=S schedstat=( 93912199183 67364592009 177636 ) utm=7567 stm=1824 core=1 HZ=100
  | heldMutexes=
 at android.hardware.display.DisplayManagerGlobal.getDisplayInfo(DisplayManagerGlobal.java:172)
 at android.hardware.display.DisplayManagerGlobal.getDisplayInfo(DisplayManagerGlobal.java:166)
 at android.hardware.display.DisplayManagerGlobal.getDisplayInfo(DisplayManagerGlobal.java:159)
  • 分析
    • cgrp=apps/bg_non_interactive 表示app在后台;
    • sCount=1有一个线程被挂起;
    • nice=0 压后台时,线程优先级降低,nice值越小(负数),优先级越高
    • schedstat( 93912199183 67364592009 177636 ),表示线程执行时间很长
Native
  • case 1
"main" prio=5 tid=1 Native
  | group="main" sCount=0 dsCount=0 flags=0 obj=0x727c02f8 self=0xb400007a2f210800
  | sysTid=339 nice=-10 cgrp=default sched=0/0 handle=0x7ab698d500
  | state=? schedstat=( 0 0 0 ) utm=0 stm=0 core=0</
### Android 开发ANR 分析与解决方案 #### 获取 `trace.txt` 文件 当应用程序未响应 (ANR) 发生时,Android 系统会在 `/data/anr/` 路径下生成名为 `traces.txt` 的日志文件。此文件包含了所有线程的堆栈信息,尤其是主线程的状态,有助于定位导致 ANR 的根本原因[^2]。 为了从设备中提取该文件,可以使用 ADB 命令: ```bash adb pull /data/anr/traces.txt ``` 此外,在每次发生 ANR 事件时,Logcat 日志也会记录 `trace.txt` 文件的具体路径。某些集成开发环境(IDE),如 Android Studio,允许开发者在程序运行期间直接查看这些 ANR 信息。 #### 分析 `trace.txt` 结构 `trace.txt` 文件通常由多个部分组成,每一部分对应一个进程内的不同线程状态。对于每个线程而言,文件会显示其名称、优先级以及当前正在执行的方法调用链路。特别需要注意的是 "main" 或者 "UI thread" 下的内容,因为大多数情况下,ANR 是由于长时间阻塞 UI 线程而引起的。 #### 使用 StrictMode 进行预防性检测 为了避免潜在的应用无响应情况,建议在开发过程中利用 Android SDK 提供的 `StrictMode` 工具类来进行监控。通过配置合适的策略选项,能够及时捕获那些可能引发 ANR 的行为模式,比如在网络请求或磁盘读写操作发生在主线程上的情形。这使得开发者能够在早期阶段识别并修正此类问题[^3]。 #### 处理已发生的 ANR 错误 一旦确认了造成 ANR 的具体位置,则应采取措施优化相应代码逻辑,确保任何耗时任务都不会影响到用户体验流畅度。常见的改进方法包括但不限于: - 将耗时较长的任务移至后台工作队列; - 减少不必要的资源加载次数; - 对频繁访问的数据源实施缓存机制; - 合理规划异步回调函数的设计思路; 综上所述,通过对 `trace.txt` 文件的有效解读和借助像 `StrictMode` 这样的辅助工具,可以帮助我们更好地理解和应对 Android 应用中存在的 ANR 挑战[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值