На нашем сервере у нас начались проблемы с OutOfMemoryError
. Мы проанализировали дампы кучи с помощью Eclipse Memory Analysis и обнаружили, что многие объекты удерживались для финализации (около 2/3 кучи):
Мы обнаружили, что это может быть какая-то блокировка метода finalize(). Я нашел несколько отчетов об ошибках, связанных с этой проблемой (здесь или здесь), и это всегда проявлялось в стеке потоков Finalizer. , что его где-то заблокировали. Но в нашем случае этот поток ЖДАЛ:
"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)
ИЗМЕНИТЬ:
Затем мы попытались добавить -XX:+UseConcMarkSweepGC
, но безуспешно, уменьшилась только частота OutOfMemoryError
, так что сначала мы подумали, что это помогло.
Наконец, мы заподозрили баг JVM и обновились с OpenJDK 1.6.0_30 до Oracle JDK 1.7.0_51, и проблема исчезла (по крайней мере, так кажется, за последние 4 часа используемая куча не растет). Мы не помним никаких изменений в методе финализации, и мы не обновляли никакую библиотеку, за это время были лишь незначительные изменения. Проблема не воспроизводится на нашем тестовом сервере с той же конфигурацией, за исключением того, что это 64-битная JVM, а рабочий сервер — 32-битный.
Возникает вопрос: что может быть причиной того, что объекты не завершаются, а поток Finalizer
ожидает следующего объекта? Правильно ли мы проанализировали дамп кучи?
Спасибо за все ответы.
ReferenceQueue.remove()
), что означает отсутствие объектов для финализации. Как вы пришли к выводу, что этоfinalize()
блокировка метода? Вы активно используетеfinalize()
в своем коде? - person Kayaman   schedule 07.03.2014