诊断ANR的一般指南

rou*_*uen 10 android android-anr-dialog

包含ANR跟踪文件有很多问题,答案总是"哦,问题在你的主题76,修复你的http调用"或者其他东西:)但我找不到任何关于如何阅读这些跟踪的一般指南或教程,任何ANR的一步一步.有没有?我特别提出几个问题:

  1. 是否总能看到我在谷歌控制台中看到的真实ANR的线程痕迹问题?或者是否可能没有相关信息,如果我无法在本地重现ANR,我运气不好?

  2. 这些信息中包含哪些主题?我想应用程序进程中有所有线程,但其余的呢?它们在某种程度上与我相关吗?(例如我的一些线程正在等待的线程等)或者还有完全不相关的进程?

  3. 谷歌游戏控制台如何确定ANR发生的"地点" - 然后显示在ANR列表中,例如:

ANR keyDispatchingTimedOut

miesto:com.sample.myapp/myapp.activities.SplashActivity

因为SplashActivity在线程跟踪的提供文本中无处可见.

  1. 我知道我应该寻找WAIT状态下的线程来寻找潜在的死锁等等.线程在"等待自己"的情况怎么样?

"AsyncTask#1"prio = 5 tid = 15 WAIT | group ="main"sCount = 1 dsCount = 0 obj = 0x41bb50c0 self = 0x5529a868 | sysTid = 2448 nice = 0 sched = 0/0 cgrp = apps handle = 1429609576 | state = S schedstat =(18097077 39273309 41)utm = 1 stm = 0 core = 1 at java.lang.Object.wait(Native Method) - 等待tid = 15持有的<0x41bb5258>(java.lang.VMThread) (AsyncTask#1)

这总是好的,我可以假设这不是原因吗?那个情况怎么样,我在NATIVE中只有一堆线程(包括主线程)和WAIT中的一堆线程在这样等待自己?这怎么可能是ANR?

fad*_*den 5

系统向您的应用程序发送各种事件,这些事件在 UI 线程上接收。如果该线程在特定时间段内未响应事件,则系统会断定该应用程序无响应,并启动 ANR 处理。

逐点解决您的问题:

  1. 并不总是可以在堆栈跟踪中看到问题。系统服务器进程检测到存在问题,然后向有问题的进程发出信号以转储其堆栈跟踪。如果应用程序在问题发现和堆栈转储信号之间恢复,那么跟踪不会告诉你太多。

  2. 您应该看到来自您的应用程序的所有线程,并且只能看到您的应用程序。ANR 机制不会尝试确定一组“相关”线程。开始的地方是 UI 线程,通常是应用程序的“主”线程,看看你是否在卡住的行为中发现了它。有时应用程序很慢,没有卡住,缓慢的原因实际上是一个不同的进程,它正在占用 CPU 或磁盘带宽,但是你在堆栈跟踪中看不到......而且你可能会得到一个堆栈反映执行超过“卡住”点的跟踪。

  3. “地点”是未响应的事件(在本例中为关键事件),以及系统试图与之交互的 Activity。

  4. 这是正常的;当一个线程通过java.util.concurrent.locks.LockSupport.park()Dalvik被“停放”时,你会看到。请记住,锁在线程等待时被释放,因此在这种情况下,它只是在等待另一个线程出现并通知它。

解决评论中提出的一点:如果 (1) 本机崩溃没有完全杀死应用程序,则本机崩溃可能会导致 ANR,这是它应该做的;(2) 死亡的线程是 UI 线程,或者持有 UI 线程正在等待的资源。如果您无权访问完整的 logcat,您可以检查线程列表以确认您的所有线程都处于活动状态。

在查看 ANR 时,您需要弄清楚的第一件事是它是永久卡住还是只是暂时放缓。这对于使用该应用程序的人来说应该是显而易见的。永久冻结通常是最容易解决的,因为堆栈跟踪通常会引导您找出问题所在。从 UI 线程开始并遍历跟踪,直到找到一些正在旋转或卡在本机调用中的代码。(虽然本机调用有一个技巧——如果它说 NATIVE 那么它仍然在本机代码中,但是如果它在堆栈顶部带有本机方法的线程上说 SUSPENDED,那么它没有被卡住,而是在行动中从本机代码返回到托管代码。)

瞬态 ANR 可能更难,尤其是当它们发生在配置未知的客户设备上时。如果他们在后台运行 CPU 基准测试,而该设备由于闪存部件故障而停止运行,那么您的应用程序将会有一段糟糕的时光。有时,堆栈跟踪会将您指向问题的大致方向(例如,在问题中,呈现缓慢且粗锁导致 UI 线程停顿),有时会在应用程序恢复正常运行后捕获跟踪。


kle*_*erg 4

它可能不是您正在寻找的检测 ANR 的总体通用方法,但一个好的开始是为您的应用程序启用严格模式。

您将能够检查 logcat,当您做错事情时系统会通知您。

只需将这些行添加到您的应用程序或活动的 onCreate() 方法中:

if (BuildConfig.DEBUG) {
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectDiskReads()
                .detectDiskWrites()
                .detectAll()
                .penaltyLog()
                .build());

        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectLeakedSqlLiteObjects()
                .detectLeakedClosableObjects()
                .penaltyLog()
                .build());
    }
Run Code Online (Sandbox Code Playgroud)

更多详细信息请参见:http://developer.android.com/reference/android/os/StrictMode.html