有没有办法找出我的应用程序扔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方法.
谢谢.
当在"主"线程中发生一些长操作时,会发生ANR.这是事件循环线程,如果它很忙,Android无法处理应用程序中的任何其他GUI事件,从而抛出ANR对话框.
现在,在您发布的跟踪中,主线程似乎做得很好,没有问题.它在MessageQueue中空闲,等待另一条消息进来.在你的情况下,ANR可能是一个更长的操作,而不是永久阻塞线程的东西,所以事件线程在操作完成后恢复,你的跟踪经历了在ANR之后.
如果ANR是永久性块(例如,死锁获取某些锁),则检测ANR发生的位置很容易,但如果它只是暂时的延迟则更难.首先,查看代码并查找可用的点和长时间运行的操作.示例可以包括在事件线程内使用套接字,锁,线程休眠和其他阻塞操作.你应该确保这些都发生在不同的线程中.如果没有任何问题,请使用DDMS并启用线程视图.这会显示应用程序中的所有线程与您拥有的跟踪类似.重现ANR,同时刷新主线程.这应该向你展示ANR时正在发生的事情
您可以在API级别9及更高级别启用StrictMode.
StrictMode最常用于捕获应用程序主线程上的意外磁盘或网络访问,其中接收UI操作并进行动画.通过保持应用程序的主线程响应,您还可以防止向用户显示ANR对话框.
public void onCreate() { StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectAll() .penaltyLog() .penaltyDeath() .build()); super.onCreate(); }
使用
penaltyLog()
您可以在使用应用程序时查看adb logcat的输出,以便在发生违规时查看违规行为.
您想知道哪个任务持有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状态!找主要原因!
跟踪并不总是包含"等待锁定".在这种情况下,很难找到主要原因.
我过去几个月一直在学习android,所以我远非专家,但我对ANR的文档感到非常失望.
大多数建议似乎都是为了避免它们或通过盲目查看代码来修复它们,这很好,但我找不到任何关于跟踪的分析.
使用ANR日志确实需要查找三件事.
1)死锁:当线程处于WAIT状态时,您可以查看详细信息以查找它的"holdby =".大多数情况下,它将由它自己保留,但如果它由另一个线程持有,那很可能是一个危险信号.去看看那个帖子,看看它的含义.你可能会发现一个循环,这是一个明显的迹象,表明出了问题.这是非常罕见的,但这是第一点,因为当它发生时,这是一场噩梦
2)主线程等待:如果你的主线程处于WAIT状态,检查它是否被另一个线程持有.这不应该发生,因为您的UI线程不应该由后台线程持有.
这两种情况都意味着您需要对代码进行重大修改.
3)主线程上的大量操作:这是ANR最常见的原因,但有时候难以找到并修复.看一下主要的线程细节.向下滚动堆栈跟踪,直到看到您识别的类(来自您的应用程序).查看跟踪中的方法,并确定您是否在这些地方进行网络呼叫,数据库呼叫等.
最后,我为无耻地插入我自己的代码而道歉,你可以使用我在https://github.com/HarshEvilGeek/Android-Log-Analyzer上写的python日志分析器这将查看你的日志文件,打开ANR文件,找到死锁,找到等待主线程,在代理日志中查找未捕获的异常,并以相对容易阅读的方式将其全部打印出来.阅读ReadMe文件(我即将添加)以了解如何使用它.它在上周给了我很多帮助!
每当您分析时序问题时,调试通常都无济于事,因为将应用程序冻结在断点将使问题消除。
最好的选择是将许多日志记录调用(Log.XXX())插入应用程序的不同线程和回调中,并查看延迟在哪里。如果需要堆栈跟踪,请创建一个新的Exception(只需实例化一个)并记录它。