Android FinalizerDaemon挂断

时间:2016-05-03 10:03:18

标签: java android multithreading android-ndk android-runtime

我在Android应用中遇到了一个非常奇怪的问题。在某个点之后(主要活动开始并且显示片段的时候),FinalizerDaemon会停止处理对象并且垃圾不断堆积。看一下线程转储,它似乎停留在ReferenceQueue.remove()

"FinalizerDaemon@4461" daemon prio=5 waiting
  java.lang.Thread.State: WAITING
      at java.lang.Object.wait(Object.java:-1)
      at java.lang.Object.wait(Object.java:423)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:101)
      - locked <0x1173> (a java.lang.ref.ReferenceQueue)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:72)
      at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:185)
      at java.lang.Thread.run(Thread.java:818)

然而队列不是空的。如果我在使用app一段时间之后转储堆,那么队列实际上是数千个条目。数据结构也看起来不会破碎: FinalizerDaemon instance showing a non-empty ReferenceQueue

在分配和垃圾收集之后再次转储,显示队列的头部与之前的Matrix实例相同。

现在,我注意到了这一点,因为我保留了一些C ++对象,这些对象需要在某个时候发布。虽然我怀疑终结器调用JNI函数并在C ++端做一些愚蠢的操作可能会以某种方式破坏它,但我的所有日​​志都表明所有终结器都运行良好并返回而不会抛出任何东西,直到它们随机停止被调用。此外,对于终结调用来说,打破守护进程是不可能的,除了对整个应用程序或其他东西进行分类之外,因为看门狗应该处理运行时间过长并抛出异常的终结器。

我尝试了一个明确的System.runFinalization(),它所做的就是永远挂起主线程,等待从不运行的守护进程。

知道如何发生这种情况吗?

1 个答案:

答案 0 :(得分:2)

我认为这与其最终化方法中的resurrected对象有关。

我将引用此question中的段落。

  

终结器线程运行,因此垃圾收集操作清理   与对象关联的资源。如果我看到它核心,那么   终结器无法获取此对象的锁定:   java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)因为    java对象正在运行方法,因此终结器线程被锁定   直到该对象完成它的当前任务。

也许这就是你的情况。