Objetos não sendo finalizados e thread do Finalizador não fazendo nada
No nosso servidor, começamos a ter problemas comOutOfMemoryError
. Analisamos os dumps de heap usando o Eclipse Memory Analysis e descobrimos que muitos objetos foram mantidos para finalização (cerca de 2/3 do heap):
Descobrimos que pode haver algum bloqueio do método finalize (). Encontrei vários relatórios de erros desse problema (aqui ouaqui) e sempre se manifestava na pilha de encadeamentos do Finalizador, que estava bloqueada em algum lugar. Mas, no nosso caso, esse tópico estava AGUARDANDO:
"Finalizer" daemon prio=10 tid=0x43e1e000 nid=0x3ff in Object.wait() [0x43dfe000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x4fe053e8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:133)
- locked <0x4fe053e8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:149)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189)
EDITAR:
Tentamos então adicionar-XX:+UseConcMarkSweepGC
, mas sem sucesso, apenas a frequência deOutOfMemoryError
s diminuiu, então primeiro pensamos que isso ajudava.
Finalmente, suspeitamos do bug da JVM e atualizamos do OpenJDK 1.6.0_30 para o Oracle JDK 1.7.0_51, e o problema desapareceu (pelo menos parece que sim, durante as últimas 4 horas o heap usado não cresce). Não nos lembramos de nenhuma alteração no método finalize, nem atualizamos nenhuma biblioteca; houve apenas pequenos desenvolvimentos durante esse período. O problema não é reproduzido em nosso servidor de teste, com a mesma configuração, exceto que é JVM de 64 bits enquanto o servidor de produção é de 32 bits.
A questão é: qual poderia ser a causa dos objetos não serem finalizados eFinalizer
thread esperando pelo próximo objeto? Analisamos o despejo de pilha corretamente?
Obrigado por todas as respostas.