阻塞 HeapTaskDaemon 线程的 ANR
Posted
技术标签:
【中文标题】阻塞 HeapTaskDaemon 线程的 ANR【英文标题】:ANR with blocked HeapTaskDaemon thread 【发布时间】:2017-11-12 11:51:09 【问题描述】:我的 android 应用程序出现 ANR 错误。跟踪显示只有一个线程处于阻塞状态(所有其他线程都处于等待、睡眠、本机等状态),因此它似乎没有陷入死锁。我手动(直接)启动了两个线程,因此我大致知道 ANR 发生在我的应用程序的哪个部分。不幸的是,我无法理解阻塞线程的踪迹。也许有人有想法?
阻塞线程:
"HeapTaskDaemon" daemon prio=5 tid=6 Blocked
| group="system" sCount=1 dsCount=0 obj=0x12cfc8e0 self=0xab4b2bf0
| sysTid=10048 nice=0 cgrp=default sched=0/0 handle=0xf4815930
| state=S schedstat=( 113876044 26950467 98 ) utm=9 stm=2 core=5 HZ=100
| stack=0xf4713000-0xf4715000 stackSize=1038KB
| held mutexes=
native: pc 0000000000016908 /system/lib/libc.so (syscall+28)
native: pc 00000000000f604b /system/lib/libart.so (_ZN3art17ConditionVariable4WaitEPNS_6ThreadE+82)
native: pc 00000000001cddb1 /system/lib/libart.so (_ZN3art2gc13TaskProcessor7GetTaskEPNS_6ThreadE+92)
native: pc 00000000001ce2c5 /system/lib/libart.so (_ZN3art2gc13TaskProcessor11RunAllTasksEPNS_6ThreadE+60)
native: pc 000000000000036f /data/dalvik-cache/arm/system@framework@boot.oat (Java_dalvik_system_VMRuntime_runHeapTasks__+74)
at dalvik.system.VMRuntime.runHeapTasks (Native method)
- waiting to lock an unknown object
at java.lang.Daemons$HeapTaskDaemon.run (Daemons.java:355)
at java.lang.Thread.run (Thread.java:818)
这是主线程:
"main" prio=5 tid=1 Waiting
| group="main" sCount=1 dsCount=0 obj=0x74da03b0 self=0xab36bea8
| sysTid=10039 nice=13 cgrp=bg_non_interactive sched=0/0 handle=0xf77a2b34
| state=S schedstat=( 2234944203 2215960664 6968 ) utm=163 stm=60 core=6 HZ=100
| stack=0xff794000-0xff796000 stackSize=8MB
| held mutexes=
at java.lang.Object.wait! (Native method)
- waiting on <0x07456fa0> (a java.lang.Object)
at java.lang.Thread.parkFor$ (Thread.java:1220)
- locked <0x07456fa0> (a java.lang.Object)
at sun.misc.Unsafe.park (Unsafe.java:299)
at java.util.concurrent.locks.LockSupport.park (LockSupport.java:158)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt (AbstractQueuedSynchronizer.java:810)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued (AbstractQueuedSynchronizer.java:843)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire (AbstractQueuedSynchronizer.java:1172)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock (ReentrantLock.java:181)
at java.util.concurrent.locks.ReentrantLock.lock (ReentrantLock.java:257)
at android.view.SurfaceView.updateWindow (SurfaceView.java:524)
at android.view.SurfaceView$3.onPreDraw (SurfaceView.java:179)
at android.view.ViewTreeObserver.dispatchOnPreDraw (ViewTreeObserver.java:944)
at android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:2082)
at android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:1134)
at android.view.ViewRootImpl$TraversalRunnable.run (ViewRootImpl.java:6050)
at android.view.Choreographer$CallbackRecord.run (Choreographer.java:860)
at android.view.Choreographer.doCallbacks (Choreographer.java:672)
at android.view.Choreographer.doFrame (Choreographer.java:608)
at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:846)
at android.os.Handler.handleCallback (Handler.java:739)
at android.os.Handler.dispatchMessage (Handler.java:95)
at android.os.Looper.loop (Looper.java:148)
at android.app.ActivityThread.main (ActivityThread.java:5441)
at java.lang.reflect.Method.invoke! (Native method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:738)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:628)
【问题讨论】:
我在 Nexus 7 上遇到了同样的问题 你解决了这个问题,我只在Android 8.0中遇到这种情况你也是这样吗? @ingsaurabh 我也只在 Android 8.0 和 8.1 上遇到了同样的问题,你成功了吗? 很遗憾没有 你如何开始你的话题?可以发一下代码吗? 【参考方案1】:试图就这个问题提供更多信息。以便它可以帮助未来的用户。
正如你所说的只有一个线程处于阻塞状态,很明显它不是死锁。标记为 blocked 的线程通常会告诉您它们试图获取的 mutex (lock) 以及线程持有的 thread ID (tid)那个锁。
在这种特殊情况下
等待锁定未知对象
上面的行既没有告诉它试图获取什么互斥(锁),也没有告诉持有该锁的线程 ID。 (也许 HeapTaskDaemon 线程试图锁定一些本机对象,并且由于某些竞争条件而在该尝试中阻塞)。因此,只需检查以下信息并确定您的案例中的问题和/或提出有根据的猜测来防止它。
在最新版本的 Android 上,垃圾收集 (GC) 通常在名为 HeapTaskDaemon 的后台线程上运行。请注意,大量分配可能意味着在 GC 上花费的 CPU 资源更多。
如果 GC 频繁运行,Systrace 会告诉你,Android Memory Profiler 可以告诉你分配的来源。如果您尽可能避免分配,尤其是在紧密循环中,您应该不会有问题。
check this 了解更多信息。
有关 Android 中 ANR 和死锁的更多信息check this link。
希望这会有所帮助。
【讨论】:
【参考方案2】:您是否尝试在应用程序清单中设置android:largeHeap="true"
?
`
【讨论】:
以上是关于阻塞 HeapTaskDaemon 线程的 ANR的主要内容,如果未能解决你的问题,请参考以下文章