Назад | Перейти на главную страницу

Утечка памяти без кучи JVM

У меня есть Glassfish v4.0, установленный на сервере Ubuntu, работающем на виртуальной машине Java Oracle, и размер резидентной памяти процесса jvm (полученный с помощью команды «top») увеличивается до тех пор, пока у jvm не будет памяти для создания нового потока.

Что у меня есть:

В чем проблема:

Использование оперативной памяти (res memory) постоянно растет, в зависимости от использования 10-100 м / час, пока jvm не сможет выделить собственную память.

Что я пробовал:

Я хотел бы, чтобы моя JVM была стабильной, поскольку я измеряю пространство кучи + perm gen занимает всего 400-600 МБ, в то время как команда «top» показывает, что память процесса java увеличивается до 850 МБ, а затем убивает себя. Я знаю, что JVM нужно больше памяти, чем перманентное пространство и куча, но как вы думаете, я все еще выделил слишком много памяти для динамического пространства и перманентного генератора? Любая помощь или руководство будут высоко оценены.

Вывод журнала: http://pakers.lv/logs/hs_err_pid970.log Все файлы JVM: http://pakers.lv/logs/jvm_flags.txt

Обновить

Что еще я пробовал (исходя из предположений и собственных выводов):

Текущее состояние С этими изменениями я, наконец, ограничил резидентную память (использование ОЗУ) для java-процесса, который был моей целью. В моем случае 512 м кучи + 128 м перманентное пространство генерируют около 750 м резидентной памяти java-процесса, которая является стабильной. Несмотря на то, что у меня все еще есть проблемы с памятью - память кучи время от времени заполняется и приводит к зависанию веб-приложения из-за продолжающейся сборки мусора, но ОС не убивает процесс. Так что теперь мне нужно либо увеличить доступную память (ОЗУ) для системы, либо проверить использование кучи и уменьшить размер моего приложения. Поскольку мое веб-приложение основано на Java EE (с EJB), я, возможно, не смогу значительно его уменьшить. В любом случае спасибо за предложения и не стесняйтесь делиться любыми другими предложениями, если таковые имеются.

Есть несколько возможностей с учетом того, чем вы поделились, например:

  • дырявая библиотека JNI, или
  • утечка создания потока, или
  • дырявые прокси динамического кода (утечка perm-gen),

но я могу только догадываться, потому что вы не предоставили никакого вывода журнала или не указали, выдавала ли JVM OutOfMemoryException (OOM), или если возникла другая ошибка. Вы также не упомянули, какой сборщик мусора использовался, хотя, если показанные выше флаги являются единственными используемыми параметрами JVM, то это сборщик CMS.

Первый шаг - сделать действия сборщика мусора наблюдаемыми, добавив следующие флаги:

-XX:+PrintTenuringDistribution
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+HeapDumpOnOutOfMemoryError
-Xloggc:/path/to/garbage.log

Если это действительно OOM, вы можете проанализировать дамп кучи с помощью VisualVM или аналогичного инструмента. Я также использую VisualVM для мониторинга действий сборщика мусора на месте через JMX. Видимость внутренних компонентов JVM может быть включена с помощью следующих флагов JVM:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=4231
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

Дополнительные ресурсы:

Обновить

Журнал действительно помогает. Спасибо. Этот конкретный журнал показывает, что у него закончилась физическая память, прежде чем он смог увеличить кучу до настроенного максимума. Он попытался выделить ~ 77M, и физически осталось только ~ 63M:

При выделении собственной памяти (malloc) не удалось выделить 77873152 байта для фиксации зарезервированной памяти.

..

/ proc / meminfo: MemTotal: 1018724 kB MemFree: 63048 kB

Вот что бы я сделал:

  1. Уменьшите кучу, чтобы она «поместилась» на машине. Установите минимальную и максимальную кучу на одно и то же значение, чтобы вы могли сразу сказать, подойдет ли она - она ​​не запустится, если не подходит.

  2. Вы можете уменьшить размер стека Java (-Xss), но похоже, что эта штука не создает много потоков, поэтому экономия не превышает одного или двух мегабайт. Я думаю, что по умолчанию для 64-битного Linux 256k. Уменьшите его слишком сильно, и он начнет OOM-процесс для выделения стека.

  3. Повторите тест.

  4. Когда он некоторое время работает под нагрузкой, создайте дамп кучи по запросу для дифференциальной диагностики, используя jmap -dump:file=path_to_file <pid>.

  5. Должно произойти одно из двух: (а) если есть утечка, в конечном итоге она снова выйдет из строя, но тип OOM должен быть другим, или (б) утечки нет, так что сборщик мусора будет работать больше и все готово. Учитывая, что вы пробовали это раньше, вероятен первый случай, если только ваш уменьшенный максимальный размер не подошел.

  6. Если это OOM, сравните два дампа, чтобы увидеть, что выросло с использованием jhat или какой-нибудь другой анализатор кучи.

Удачи!

Попробуйте запустить процесс в 64-битном режиме, добавив: -D64 к флагам запуска JVM.

Вы можете запустить pmap $JVMPID чтобы увидеть, как распределяется виртуальная память. Запустите его до того, как он выйдет из строя.