Почему мой размер дампа кучи Java намного меньше, чем используемая память?

проблема

Мы пытаемся найти виновника большой утечки памяти в нашем веб-приложении. У нас довольно ограниченный опыт поиска утечек памяти, но мы узнали, как сделать дамп кучи Java, используя jmap и проанализировать его в Eclipse MAT.

Однако в нашем приложении, использующем 56/60 ГБ памяти, дамп кучи составляет всего 16 ГБ и еще меньше в Eclipse MAT.

контекст

Наш сервер использует Wildfly 8.2.0 в Ubuntu 14.04 для нашего Java-приложения, процесс которого использует 95% доступной памяти. При создании дампа наш буфер занимал 56 кбайт.

Мы использовали следующую команду для создания дампа: sudo -u {application user} jmap -dump:file=/mnt/heapdump/dump_prd.bin {pid}

Размер файла дампа кучи составляет 16,4 ГБ, и при анализе его с помощью Eclipse MAT указывается, что существует около 1 ГБ живых объектов и ~14,8 ГБ недоступной / мелкой кучи.

РЕДАКТИРОВАТЬ: Вот еще немного информации о проблеме, которую мы видим, происходит. Мы отслеживаем использование памяти и видим, как она растет и растет, пока не останется ~300 МБ свободной памяти. Затем он остается в пределах этого объема памяти до тех пор, пока процесс не завершится, к сожалению, без ошибок в журнале приложений.

Это заставляет нас предположить, что это серьезная ошибка OOM, потому что это происходит только тогда, когда память почти исчерпана. Мы используем настройки -Xms25000m -Xmx40000m для нашей JVM.

Вопрос

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

2 ответа

Решение

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

Как я могу получить дамп кучи на Java 5 без предварительного сбора мусора?

По моему опыту, в истинной ошибке OutOfMemoryError, где ваше приложение просто требует больше места в куче, чем доступно, этот GC - это дурацкое поручение, и окончательный дамп кучи будет размером с макс. размер кучи.

Когда дамп кучи намного меньше, это означает, что в системе не было действительно нехватки памяти, но, возможно, имелась нехватка памяти. Например, есть java.lang.OutOfMemoryError: GC overhead limit exceeded ошибка, которая означает, что JVM могла освободить достаточно памяти для обслуживания нового запроса на выделение, но ей пришлось потратить слишком много времени на сбор мусора.

Также возможно, что у вас нет проблем с памятью. Что заставляет вас думать, что вы делаете? Вы ничего не упомянули об использовании кучи или об ошибке OutOfMemoryError. Вы упомянули только объем памяти JVM в операционной системе.

По моему опыту, наличие дампа кучи намного меньше, чем используемая реальная память, может быть связано с утечкой в ​​JNI.

Несмотря на то, что вы не используете напрямую какой-либо нативный код, есть определенные библиотеки, которые используют его для ускорения.

В нашем случае это был Дефлатер и Инфлятор, который не закончился должным образом.

Другие вопросы по тегам