java android multithreading android-ndk android-runtime

java - Android FinalizerDaemon colgando



multithreading android-ndk (1)

Estoy teniendo un problema realmente extraño en una aplicación de Android. Después de un cierto punto (alrededor de cuando comienza la actividad principal y se muestra un fragmento), el FinalizerDaemon simplemente deja de procesar los objetos y la basura sigue acumulándose. Al ver un volcado de hilos, parece estar atascado en 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)

Sin embargo, la cola no está vacía. Si vuelco el montón después de usar la aplicación por un tiempo, la cola es literalmente de miles de entradas. La estructura de datos tampoco se ve rota:

Volcar nuevamente después de asignar y recolectar basura muestra que el encabezado de la cola es la misma instancia de Matrix que antes.

Ahora, me di cuenta de esto porque estoy reteniendo algunos objetos de C ++, que deben ser liberados en algún momento. Si bien sospecho que un finalizador que llama a las funciones JNI y hace algo estúpido en el lado de C ++ podría romperlo, todos mis registros indican que todos los finalizadores funcionan bien y regresan sin lanzar nada hasta que dejan de recibir llamadas al azar. Además, realmente no debería ser posible que una llamada final rompa el Daemon, a no ser que segreguen la aplicación completa o algo así, ya que el Watchdog debe manejar los finalizadores que se ejecutan durante demasiado tiempo y arrojan una excepción.

Intenté un System.runFinalization() explícito y todo lo que hace es colgar el hilo principal para siempre, esperando el demonio que nunca se ejecuta.

¿Alguna idea de cómo podría pasar esto?


Creo que esto tiene que ver con algunos objetos resurrected en sus métodos de finalización.

Citaré un párrafo de esta question .

El subproceso finalizador se ejecuta para que la recolección de basura funcione para limpiar los recursos asociados con un objeto. Si lo estoy viendo correctamente, el finalizador no puede obtener el bloqueo para este objeto: java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:118) porque el objeto java está ejecutando un método , por lo que el subproceso finalizador es bloqueado hasta que el objeto termine con su tarea actual.

Tal vez esa es la situación que tienes.