Охота на утечки памяти, VisualVM: «Корень GC не найден».Что дальше? - PullRequest
12 голосов
/ 13 декабря 2011

У меня есть дамп памяти, который я сделал из умирающего приложения.Он израсходовал всю доступную кучу (-Xmx1024m).Он использует com.gargoylesoftware.htmlunit.WebClient для сканирования веб-страниц.Делает несколько http запросов в минуту, умирает через несколько дней.Как видно из дампа, у него ~ 1750 экземпляров класса HtmlPage, каждый с тонами связанных объектов, включая полное содержимое просканированной страницы.

Я не могу понять, почему HtmlPage не являютсямусор собрал.Я исследовал ссылки на экземпляры, и я не вижу своего кода, содержащего ссылку на него, и VisualVM говорит, что «корень GC не найден».Как я понимаю, это должно означать, что объект имеет право на gc, но он не работает.

Приложение работает как простой автономный процесс, оно не использует веб-контейнеры или серверы приложений.

Есть намеки?На что еще мне обратить внимание?

Характеристики:

  • htmlunit v2.7
  • Java-версия "1.6.0_13"Среда выполнения Java (TM) SE (сборка 1.6.0_13-b03) Серверная виртуальная машина Java HotSpot (TM) (сборка 11.3-b02, смешанный режим)
  • Linux my.lan 2.6.18-128.el5 # 1SMP ср 17 дек 11:42:39 EST 2008 i686 i686 i386 GNU / Linux

Update1

Я попытался проанализировать дамп с помощьюYourKit Java Profiler.Он показывает мне много java.lang.ref.Finalizer объектов с сохраненным размером 310 МБ.Они созданы для финализатора net.sourceforge.htmlunit.corejs.javascript.NativeGenerator#finalize(), а NativeGenerator относится к Window, затем к HtmlPage и ко всему.

Кто-нибудь знает, почему они остаются в памяти?

Примечание : Любопытно, но VisualVM показывал "ожидающий финализацию" как ноль.

Ответы [ 2 ]

1 голос
/ 11 марта 2012

Когда у объекта есть нетривиальный метод finalize (), при создании экземпляра объекта JVM создает java.lang.ref.Finalizer, который содержит ссылку на созданный объект, поэтому он не получает мусор перед методом finalize () закончен. Утечка памяти происходит из-за того, что java.lang.ref.Finalizer-s не очищается вовремя. Очистка этих финализаторов выполняется отдельным потоком демона финализатора с более низким приоритетом, поэтому, если вы создаете много экземпляров объектов с реализованным методом finalize (), со временем у вас заканчивается память.

Все очень хорошо описано в:

http://www.fasterj.com/articles/finalizer2.shtml

Вот что они предлагают в качестве решения:

"Одним из очевидных способов является повышение приоритета потока демона" Финализатор "- для этого нет API, поэтому вам нужно пройти через все потоки, чтобы найти его по имени, а затем увеличить его приоритет."

Удачи

1 голос
/ 13 декабря 2011

Убедитесь, что вы вызываете webClient.closeAllWindows () после завершения работы со страницами. В противном случае поток JavaScript продолжает работать, сохраняя ссылки на ресурсы страницы и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...