Подтвердить что ты не робот

Свалка кучи Java и размер кучи после анализа кучи различаются

Я испытываю утечку памяти, и здесь идет некоторая деталь.

Во время утечки,

  • топ показывает 50 ГБ памяти как жилой
  • Размер файла дампа кучи составляет 25 ГБ
  • Анализатор Eclipse MAT говорит мне, что размер кучи составляет 10 ГБ

Во время до утечки,

  • верхняя показывает 30 ГБ памяти как жилой
  • Размер файла дампа кучи составляет 20 ГБ
  • Анализатор Eclipse MAT говорит мне, что размер кучи составляет 10 ГБ

Я очень удивлен, что разница между верхом, размером дампа кучи и фактическим размером кучи. Я предполагаю, что разница между вершиной и кучей заключается в возможности кучи сборщика мусора и областей собственной кучи. Но почему размер файла дампа кучи и фактический размер кучи (из анализатора eclipse MAT) могут отличаться?

Любое понимание этой проблемы?

ОБНОВЛЕНИЕ/ОТВЕТ

Некоторые из предложений заключаются в том, чтобы использовать jcmd (https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html), поскольку веб-сайт сообщает "Отслеживание встроенной памяти". Но, если вы внимательно прочитаете страницу, вы увидите

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

Так что, в случае утечки внутри собственной библиотеки, jcmd не вариант.

После нескольких дней сканирования Интернета и опробования различных профилировщиков наиболее эффективным для этой проблемы является использование профилировщика jemalloc.

Эта страница мне очень помогла! https://gdstechnology.blog.gov.uk/2015/12/11/using-jemalloc-to-get-to-the-bottom-of-a-memory-leak/

4b9b3361

Ответ 1

top и другие инструменты уровня ОС показывают, сколько системной памяти потребляет ваш JVM-процесс. Куча Java, определяемая параметром командной строки -Xmx, является только частью этой памяти. Помимо кучи JVM нужна некоторая память для себя. Затем есть потоки java, каждый из которых требует определенного объема памяти. И метапас/постоянное поколение. И еще несколько. Вы можете прочитать этот пост в блоге и этот ответ "SO" для получения дополнительной информации.

Что касается размера файла дампа и фактического размера кучи, то ответ @arnab-biswas, безусловно, верен. MAT сообщает размер фактически используемой кучи, потребляемой живыми объектами. Но куча дампа содержит всю кучу, включая мусор.

Ответ 2

У меня сложилась аналогичная ситуация. Разница (размер файла HPROF - размер кучи, обозначенный MAT) - фактически мусор (недостижимые объекты). Недостижимый объект Гистограмма в MAT должна помочь здесь.

jmap -F -dump:live,format=b,file=<file_name.hprof> <process_id> будет удалять только живые объекты и НЕ мусор.

Ответ 3

Для мониторинга собственной памяти вам нужно запустить приложение с помощью -XX:NativeMemoryTracking=summary или -XX:NativeMemoryTracking=detail. Обратите внимание, что существует штраф за производительность, поэтому дважды подумайте, прежде чем делать это на производстве.

Когда функция отслеживания памяти активна, вы можете использовать jcmd <pid> VM.native_memory summary. Также доступны другие команды, проверьте https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html или найдите отслеживание встроенной памяти.

EDIT: я не следил за ссылками до ответа, вы можете искать что-то вроде https://github.com/jeffgriffith/native-jvm-leaks вместо.

Ответ 4

Вы запрашиваете ответ из достоверных/официальных источников. Позвольте мне попробовать.

1) почему память, используемая моим процессом JVM (показана сверху), больше, чем размер кучи?

Потому что общее потребление памяти процессом JVM состоит из большего количества вещей, чем просто куча Java. Несколько примеров:

  • Сгенерированный (JIT: ed) код
  • Загруженные библиотеки (включая файлы jar и class)
  • Управляющие структуры для Java-кучи
  • Стеки потоков
  • Собственная память пользователя (malloc: ed в JNI)

Достоверные/официальные источники: области данных времени выполнения и этот блог

2) почему размер дампа кучи намного больше, чем сообщает MAT?

Потому что MAT не показывает полную кучу. Во время создания индекса анализатор памяти удаляет недостижимые объекты, потому что различные алгоритмы сборщика мусора имеют тенденцию оставлять некоторый мусор позади.

Достоверные/официальные источники: MemoryAnalyzer/FAQ

Ответ 5

Дамп кучи: Дамп кучи - это моментальный снимок памяти процесса Java в определенный момент времени. Существуют разные форматы для сохранения этих данных, и в зависимости от формата он может содержать разные фрагменты информации, но в целом моментальный снимок содержит информацию о объектах и ​​классах Java в куче в момент запуска моментального снимка. Обычно полный GC запускается до того, как дамп кучи написан, поэтому он содержит информацию об остальных объектах.

Информацию о MAT, найденную здесь http://help.eclipse.org/neon/index.jsp?topic=/org.eclipse.mat.ui.help/welcome.html