ANR与阻塞的HeapTaskDaemon线程

时间:2017-06-10 15:35:48

标签: java android multithreading

我的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)

3 个答案:

答案 0 :(得分:2)

试图在此问题上提供更多信息。这样可以为将来的用户提供帮助。

正如您所说的那样,只有一个线程处于 Blocked 状态,这显然不是死锁。标记为 blocked 的线程通常会告诉您它们试图获取什么 mutex(锁定)以及线程持有的 thread ID(tid)那个锁。

在这种情况下

  • 等待锁定未知对象

上一行既不告诉它试图获取什么互斥锁(锁),也不告诉持有该锁的线程ID。 (也许HeapTaskDaemon线程试图锁定某些本机对象,并且由于某些竞争条件而在该try块中)。因此,仅需检查以下信息并确定您所遇到的问题,并/或提出有根据的猜测以防止出现此问题。

在最新版本的Android上,垃圾回收(GC)通常在名为 HeapTaskDaemon 的后台线程上运行。请注意,大量分配可能意味着更多的CPU资源用于GC。

Systrace将显示GC是否频繁运行,而Android Memory Profiler可以显示分配来自何处。如果您在可能的情况下避免分配,尤其是在紧密循环中,那应该没有问题。

check this了解更多信息。

有关Android check this link中ANR和死锁的更多信息。

希望这会有所帮助。

答案 1 :(得分:0)

好像您的 SurfaceView 正在用ReentrantLock锁定线程,但是在设置WaitLock和 ReentrantLock 后可能初始化有问题>通过 SurfaceView 保持锁定,这导致您的线程被阻止,通常称为 Jank

您应该自行尝试调试,使用Systrace查找导致空白的原因,并在此处启用GPU渲染和粘贴Systrace数据,以便我可以进行审核,并在可能的情况下提供任何解决方案。

答案 2 :(得分:0)

您是否尝试在应用清单中设置android:largeHeap="true"? `