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)
それでもキューは空ではありません。アプリをしばらく使用した後にヒープをダンプすると、キューは文字通り何千ものエントリになります。データ構造も壊れているようには見えません。
割り当てとガベージ コレクションを行った後に再度ダンプすると、キューの先頭が以前と同じ Matrix インスタンスであることがわかります。
これは、ある時点でリリースする必要があるいくつかの C++ オブジェクトを保持しているためです。ファイナライザーが JNI 関数を呼び出して C++ 側で愚かなことをすると、何らかの形でそれが壊れる可能性があると思いますが、すべてのログは、すべてのファイナライザーが正常に実行され、ランダムに呼び出されなくなるまで何もスローせずに戻ることを示しています。また、ウォッチドッグは実行時間が長すぎて例外をスローするファイナライザーを処理することになっているため、ファイナライズ呼び出しでデーモンを壊すことは実際には不可能です。
明示的に試してみましたSystem.runFinalization()
が、実行されないデーモンを待って、メインスレッドを永久にハングアップさせるだけです。
これがどのように起こるか考えていますか?