Подтвердить что ты не робот

Android FinalizerDaemon повесил трубку

У меня очень странная проблема в Android-приложении. После определенного момента (вокруг, когда начинается основная активность и отображается фрагмент) FinalizerDaemon просто прекращает обработку объектов, а мусор продолжает накапливаться. Если посмотреть на дамп потока, он, похоже, застрял на ReferenceQueue.remove():

"[email protected]" 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)

Но очередь не пуста. Если я сбрасываю кучу после использования приложения некоторое время, очередь составляет буквально тысячи записей. Структура данных также не выглядит разбитой: экземпляр FinalizerDaemon, показывающий непустую ReferenceQueue

Сброс снова после выделения и удаления мусора еще несколько показывает, что глава очереди - это тот же экземпляр матрицы, что и раньше.

Теперь я заметил это, потому что я сохраняю некоторые объекты на С++, которые нужно в какой-то момент выпустить. Хотя я подозреваю, что финализатор, вызывающий функции JNI и делающий что-то глупое на стороне С++, может как-то сломать его, все мои журналы показывают, что все финализаторы работают нормально и возвращаются, не бросая ничего, пока они просто случайно не перестанут получать вызов. Кроме того, не должно быть действительно возможно, чтобы завершить вызов для разрыва Демона, не выполнив segfaulting всего приложения или что-то еще, поскольку Watchdog должен обрабатывать финализаторы, которые работают слишком долго и генерируют исключение.

Я попробовал явный System.runFinalization(), и все, что он делает, вечно вешает основной поток, ожидая, что демон не будет работать.

Любая идея, как это могло произойти?

4b9b3361

Ответ 1

Я считаю, что это связано с тем, что некоторые объекты воскресают в своих методах завершения.

Я приведу параграф из этого question.

Запуск финализатора выполняется так, что сбор мусора работает для очистки которые связаны с объектом. Если я увижу это по- финализатор не может получить блокировку этого объекта: java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118), потому что объект java использует метод, поэтому поток финализатора заблокирован пока этот объект не завершит текущую задачу.

Возможно, ситуация у вас есть.