Java 带有阻塞HeapTaskDaemon线程的ANR

Java 带有阻塞HeapTaskDaemon线程的ANR,java,android,multithreading,Java,Android,Multithreading,我的Android应用程序中出现了一个ANR错误。跟踪显示只有一个线程处于阻塞状态(所有其他线程都处于等待状态、休眠状态、本机状态等等),因此它似乎没有处于死锁状态。有两个线程是我手动(直接)启动的,所以我大致知道ANR发生在我的应用程序的哪个部分。不幸的是,我无法理解阻塞线程的轨迹。也许有人有主意 阻塞线程: "HeapTaskDaemon" daemon prio=5 tid=6 Blocked | group="system" sCount=1 dsCount=0 obj=0x12cf

我的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)
“主”优先级=5 tid=1等待
|group=“main”scont=1 dsCount=0 obj=0x74da03b0 self=0xab36bea8
|sysTid=10039 nice=13 cgrp=bg_非交互式计划=0/0句柄=0xf77a2b34
|state=S schedstat=(2234944203 2215960664 6968)utm=163 stm=60芯=6赫兹=100
|堆栈=0xff794000-0xff796000堆栈大小=8MB
|保持互斥=
在java.lang.Object.wait!(本机方法)
-等待(一个java.lang.Object)
位于java.lang.Thread.parkFor$(Thread.java:1220)
-锁定(一个java.lang.Object)
位于sun.misc.Unsafe.park(Unsafe.java:299)
位于java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
位于java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:810)
位于java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:843)
位于java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1172)
位于java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:181)
位于java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:257)
在android.view.SurfaceView.updateWindow(SurfaceView.java:524)
在android.view.SurfaceView$3.onPreDraw(SurfaceView.java:179)
在android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:944)
在android.view.ViewRootImpl.performTraversals上(ViewRootImpl.java:2082)
位于android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1134)
在android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6050)
在android.view.Choreographer$CallbackRecord.run(Choreographer.java:860)
位于android.view.Choreographer.doCallbacks(Choreographer.java:672)
位于android.view.Choreographer.doFrame(Choreographer.java:608)
在android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:846)中
位于android.os.Handler.handleCallback(Handler.java:739)
位于android.os.Handler.dispatchMessage(Handler.java:95)
在android.os.Looper.loop(Looper.java:148)
位于android.app.ActivityThread.main(ActivityThread.java:5441)
在java.lang.reflect.Method.invoke!(本机方法)
在com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run上(ZygoteInit.java:738)
位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)

似乎您的SurfaceView正在用锁定线程,但在设置WaitLock后,初始化时可能出现问题,并且可重入锁定SurfaceView锁定,这会导致线程阻塞,通常称为Jank


您应该自己尝试调试,使用查找导致Jank的原因,同时启用GPU渲染并在此处粘贴Systrace数据,以便我可以查看并提供任何解决方案(如果可能)。

尝试提供有关此问题的更多信息。因此,它可以帮助未来用户的

正如您所说,只有一个线程处于阻塞状态,很明显,这不是死锁。标记为blocked的线程通常会告诉您它们试图获取的互斥锁(lock)以及持有该锁的线程的线程ID(tid)

在这种特殊情况下

  • 正在等待锁定未知对象
上面的行既不告诉它试图获取什么互斥锁,也不告诉持有该锁的线程ID。(可能是HeapTaskDaemon线程试图锁定某个本机对象,并且由于某些争用条件而处于该尝试块中)。因此,只需检查以下信息,并确定您案例中的问题和/或提出有根据的猜测,以防止它

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

Systrace将向您显示GC是否经常运行,并且可以向您显示分配的来源。如果您尽可能避免分配,特别是在紧循环中,您应该不会有问题

了解更多信息

有关Android中ANR和死锁的更多信息


希望这会有所帮助。

您是否尝试过在应用程序清单中设置android:largeHeap=“true”?
`

我在Nexus 7Ddd上遇到了同样的问题。你解决了这个问题,我在安卓8.0上遇到了同样的问题。你也是这样吗?@ingsarabh我也在安卓8.0和8.1上遇到了同样的问题,你成功了吗?不幸的是,你怎么启动你的线程?你能把密码寄出去吗?