当前位置:  开发笔记 > 编程语言 > 正文

Android - 如何调查ANR?

如何解决《Android-如何调查ANR?》经验,为你挑选了5个好方法。

有没有办法找出我的应用程序扔ANR(应用程序无响应)的位置.我看了/ data中的traces.txt文件,我看到了我的应用程序的跟踪.这就是我在追踪中看到的.

DALVIK THREADS:
"main" prio=5 tid=3 TIMED_WAIT
  | group="main" sCount=1 dsCount=0 s=0 obj=0x400143a8
  | sysTid=691 nice=0 sched=0/0 handle=-1091117924
  at java.lang.Object.wait(Native Method)
  - waiting on <0x1cd570> (a android.os.MessageQueue)
  at java.lang.Object.wait(Object.java:195)
  at android.os.MessageQueue.next(MessageQueue.java:144)
  at android.os.Looper.loop(Looper.java:110)
  at android.app.ActivityThread.main(ActivityThread.java:3742)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:515)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
  at dalvik.system.NativeStart.main(Native Method)

"Binder Thread #3" prio=5 tid=15 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x434e7758
  | sysTid=734 nice=0 sched=0/0 handle=1733632
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #2" prio=5 tid=13 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x433af808
  | sysTid=696 nice=0 sched=0/0 handle=1369840
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #1" prio=5 tid=11 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x433aca10
  | sysTid=695 nice=0 sched=0/0 handle=1367448
  at dalvik.system.NativeStart.run(Native Method)

"JDWP" daemon prio=5 tid=9 VMWAIT
  | group="system" sCount=1 dsCount=0 s=0 obj=0x433ac2a0
  | sysTid=694 nice=0 sched=0/0 handle=1367136
  at dalvik.system.NativeStart.run(Native Method)

"Signal Catcher" daemon prio=5 tid=7 RUNNABLE
  | group="system" sCount=0 dsCount=0 s=0 obj=0x433ac1e8
  | sysTid=693 nice=0 sched=0/0 handle=1366712
  at dalvik.system.NativeStart.run(Native Method)

"HeapWorker" daemon prio=5 tid=5 VMWAIT
  | group="system" sCount=1 dsCount=0 s=0 obj=0x4253ef88
  | sysTid=692 nice=0 sched=0/0 handle=1366472
  at dalvik.system.NativeStart.run(Native Method)

----- end 691 -----

我怎样才能找出问题所在?跟踪中的方法都是SDK方法.

谢谢.



1> sooniln..:

当在"主"线程中发生一些长操作时,会发生ANR.这是事件循环线程,如果它很忙,Android无法处理应用程序中的任何其他GUI事件,从而抛出ANR对话框.

现在,在您发布的跟踪中,主线程似乎做得很好,没有问题.它在MessageQueue中空闲,等待另一条消息进来.在你的情况下,ANR可能是一个更长的操作,而不是永久阻塞线程的东西,所以事件线程在操作完成后恢复,你的跟踪经历了在ANR之后.

如果ANR是永久性块(例如,死锁获取某些锁),则检测ANR发生的位置很容易,但如果它只是暂时的延迟则更难.首先,查看代码并查找可用的点和长时间运行的操作.示例可以包括在事件线程内使用套接字,锁,线程休眠和其他阻塞操作.你应该确保这些都发生在不同的线程中.如果没有任何问题,请使用DDMS并启用线程视图.这会显示应用程序中的所有线程与您拥有的跟踪类似.重现ANR,同时刷新主线程.这应该向你展示ANR时正在发生的事情


堆栈跟踪显示主线程在Looper(消息循环实现)中并通过Object.wait进行定时等待.这意味着消息循环当前没有任何要分派的消息,并且正在等待新消息进入.当系统实现消息循环花费大量时间处理消息而不处理其他消息时,会发生ANR.队列.如果循环正在等待消息,显然这不会发生.
有关输出的详细说明,请参见http://elliotth.blogspot.com/2012/08/how-to-read-dalvik-sigquit-output.html.
唯一的问题是"重现ANR":-).你能解释一下堆栈跟踪显示主线程是"空闲"的,这会很棒.
@Soonil嗨,你知道其余的部分意味着什么像Binder线程3,Binder线程2 JDWP恶魔prio 5.什么是sCount,dsCount,obj,sysTid,漂亮的sched意味着什么.它也有VMWAIT,RUNNABLE,NATIVE等信息

2> Dheeraj V.S...:

您可以在API级别9及更高级别启用StrictMode.

StrictMode最常用于捕获应用程序主线程上的意外磁盘或网络访问,其中接收UI操作并进行动画.通过保持应用程序的主线程响应,您还可以防止向用户显示ANR对话框.

public void onCreate() {
    StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                           .detectAll()
                           .penaltyLog()
                           .penaltyDeath()
                           .build());
    super.onCreate();
}

使用penaltyLog()您可以在使用应用程序时查看adb logcat的输出,以便在发生违规时查看违规行为.


小提示 - 使用if(BuildConfig.DEBUG)...以防止包含在生产中
@MuhammedRefaat它不会阻止任何ANR.它会立即使应用程序崩溃,而不是在5秒后崩溃.例如,如果您在主线程上访问数据库并且需要2秒,那么您将无法获得ANR,但StrictMode将使应用程序崩溃.StrictMode严格用于您的调试阶段,而不是生产阶段.

3> Horyun Lee..:

您想知道哪个任务持有UI线程.跟踪文件为您提供了查找任务的提示.你需要调查每个线程的状态

线程状态

运行 - 执行应用程序代码

睡觉 - 叫做Thread.sleep()

监视器 - 等待获取监视器锁定

等待 - 在Object.wait()

原生 - 执行本机代码

vmwait - 等待VM资源

僵尸 - 线程正在死亡

init - thread正在初始化(你不应该看到这个)

开始 - 线程即将开始(你不应该看到这个)

专注于SUSPENDED,MONITOR状态.监视状态指示调查哪个线程,并且线程的SUSPENDED状态可能是死锁的主要原因.

基本调查步骤

    找"等待锁定"

    你可以找到监控状态"Binder Thread#15"prio = 5 tid = 75 MONITOR

    如果找到"等待锁定"你很幸运

    示例:等待锁定由threadid = 74持有的<0xblahblah>(com.foo.A)

    您可以注意到"tid = 74"现在正在执行任务.所以去tid = 74

    tid = 74也许是SUSPENDED状态!找主要原因!

跟踪并不总是包含"等待锁定".在这种情况下,很难找到主要原因.



4> Akhil Cheria..:

我过去几个月一直在学习android,所以我远非专家,但我对ANR的文档感到非常失望.

大多数建议似乎都是为了避免它们或通过盲目查看代码来修复它们,这很好,但我找不到任何关于跟踪的分析.

使用ANR日志确实需要查找三件事.

1)死锁:当线程处于WAIT状态时,您可以查看详细信息以查找它的"holdby =".大多数情况下,它将由它自己保留,但如果它由另一个线程持有,那很可能是一个危险信号.去看看那个帖子,看看它的含义.你可能会发现一个循环,这是一个明显的迹象,表明出了问题.这是非常罕见的,但这是第一点,因为当它发生时,这是一场噩梦

2)主线程等待:如果你的主线程处于WAIT状态,检查它是否被另一个线程持有.这不应该发生,因为您的UI线程不应该由后台线程持有.

这两种情况都意味着您需要对代码进行重大修改.

3)主线程上的大量操作:这是ANR最常见的原因,但有时候难以找到并修复.看一下主要的线程细节.向下滚动堆栈跟踪,直到看到您识别的类(来自您的应用程序).查看跟踪中的方法,并确定您是否在这些地方进行网络呼叫,数据库呼叫等.

最后,我为无耻地插入我自己的代码而道歉,你可以使用我在https://github.com/HarshEvilGeek/Android-Log-Analyzer上写的python日志分析器这将查看你的日志文件,打开ANR文件,找到死锁,找到等待主线程,在代理日志中查找未捕获的异常,并以相对容易阅读的方式将其全部打印出来.阅读ReadMe文件(我即将添加)以了解如何使用它.它在上周给了我很多帮助!



5> 小智..:

每当您分析时序问题时,调试通常都无济于事,因为将应用程序冻结在断点将使问题消除。

最好的选择是将许多日志记录调用(Log.XXX())插入应用程序的不同线程和回调中,并查看延迟在哪里。如果需要堆栈跟踪,请创建一个新的Exception(只需实例化一个)并记录它。


感谢您在需要堆栈跟踪时创建新异常的建议。这在调试时非常有用:)
推荐阅读
pan2502851807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有