Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android FinalizerDaemon hanging up

I'm having a really weird problem in an Android app. After a certain point (around when the main activity starts and a fragment is displayed) the FinalizerDaemon just stops processing objects and garbage keeps piling up. Looking at a thread dump, it seems to be stuck on 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)

Yet the queue is not empty. If I dump the heap after using app for a while, the queue is literally thousands of entries long. The data structure also doesn't look broken: FinalizerDaemon instance showing a non-empty ReferenceQueue

Dumping again after allocating and garbage collecting some more shows that the head of the queue is the same Matrix instance as before.

Now, I noticed this because I'm retaining some C++ objects, which need to be released at some point. While I suspect that a finalizer calling into JNI functions and doing something stupid on the C++ side could somehow break it, all my logs indicate that all the finalizers are running fine and returning without throwing anything until they just randomly stop getting called. Also, it shouldn't really be possible for a finalize call to break the Daemon, short of segfaulting the whole app or something, since the Watchdog is supposed to handle finalizers that run for too long and throw an exception.

I tried an explicit System.runFinalization() and all it does is hang the main thread forever, waiting for the daemon which never runs.

Any idea how this could happen?

like image 388
IvoDankolov Avatar asked May 03 '16 10:05

IvoDankolov


1 Answers

I believe this has to do with some objects being resurrected in their finalize methods.

I'll quote a paragraph from this question.

The finalizer thread runs so the garbage collection operates to clean up resources associated with an object. If I'm seeing it corectly, the finalizer can't get the lock to this object: java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118) because the java object is running a method, so the finalizer thread is locked until that object is finished with it's current task.

Maybe that's the situation you have.

like image 198
Mina Wissa Avatar answered Oct 22 '22 00:10

Mina Wissa