Ниже приведен один из примеров анализа дампа кучи, чтобы узнать, какие объекты ответственны за нехватку памяти JVM.

Как получить дамп кучи JVM?

Один из способов — иметь параметр java — XX:+HeapDumpOnOutOfMemoryError, который запускает дамп кучи, когда JVM не хватает памяти.

Другой способ — использовать jmap (доступно в jdk 1.6, но также может использоваться в jvm с 1.4+). Сначала найдите идентификатор процесса Java, используя jps

bash-4.1$ jps
24437 Jps
11036 WrapperSimpleApp

или вы также можете использовать ps -ef для получения идентификатора процесса Java.

-bash-4.1$ ps -ef | grep java
app      11036 11034  3 05:07 ?        00:26:49 /usr/lib/jvm/jdk1.6.0_151/bin/java -Xms6g -Xmx6g -XX:NewSize=3g -XX:MaxNewSize=3g -XX:PermSize=512m -XX:MaxPermSize=512m -XX:ThreadStackSize=512 -Duser.timezone=US/Central -XX:SurvivorRatio=8 ... 

Как только вы узнаете идентификатор процесса, используйте приведенную ниже команду для создания дампа кучи.

jmap -J-d64 -dump:format=b,file=<filename>.hprof <jvm-process-id>
bash-4.1$ jmap -J-d64 -dump:format=b,file=heapdump`date +%m%d%y%H%M%S`.hprof 11036

Анализ дампа кучи с помощью Eclipse Memory Analyzer

Скачать Eclipse Memory Analyzer (Для 64-битной ОС получите 64-битную версию) — https://eclipse.org/mat/
В зависимости от размера дампа вам необходимо увеличить размер виртуальной машины Eclipse MAT
Чтобы увеличить размер в Mac OS X, щелкните правой кнопкой мыши MemoryAnalyzer (приложение), затем Показать содержимое пакета.
Изменить — MemoryAnalyzer.app/Contents/MacOS/MemoryAnalyzer.ini

В приведенном ниже примере размер дампа кучи составляет 1,8 ГБ, размер виртуальной машины Eclipse MAT — «3048 м», а размер экземпляра виртуальной машины (из которого создается дамп кучи) — 2560 м.

Открыть дамп кучи -

Примечание. Если при импорте дампа кучи вы столкнулись с приведенной ниже ошибкой, добавьте -DhprofStrictnessWarning=true в MemoryAnalyzer.ini.

После загрузки дампа кучи в Eclipse Memory Analyzer
откройте дерево доминаторов.

Выберите «Группировать по классу»

Здесь вы можете узнать, какие типы объектов занимают большую часть дампа кучи.

Например — в приведенном ниже сценарии объекты GSAItem занимают 41% дампа кучи (788 МБ из 1,8 ГБ).

Чтобы узнать, какие элементы отвечают за 41%

Щелкните правой кнопкой мыши atg.adapter.gsa.GSAItem -> Список объектов -> с исходящими ссылками

После того, как объекты перечислены. Чтобы знать, что это за предметы.

В объекте GSAItem mItemDescriptor.mItemDescriptorName даст имя GSAItem.

Нам нужно сгруппировать по значению «mItemDescriptor.mItemDescriptorName» в классе atg.adapter.gsa.GSAItem (в dominator_tree).

Итак, вернитесь на вкладку dominator_tree, щелкните правой кнопкой мыши atg.adapter.gsa.GSAItem -> Основы Java -> Группировать по значению.

В окне «Группировать по значению» заполните поле «mItemDescriptor.mItemDescriptorName» и нажмите «Готово».

Это займет время в зависимости от количества объектов, которые необходимо проанализировать.

Как только это будет сделано, вы сможете увидеть, какие типы элементов (GSAItems) занимают больше места в пространстве кучи jvm. (сортировать по сохраненной куче)

В приведенном ниже сценарии элементы ss-sku занимают 333 МБ пространства кучи jvm, а количество элементов ss-sku в памяти составляет 35 465 (т. е. 35 465 элементов кэшируются в памяти).

Возьмем пример — еще один дамп кучи, 1570 объектов SamsSessionComponent заняли 49%. (1,8 ГБ из 3,4 ГБ)

Вы также можете проверить каждый из этих объектов, какие свойства (или ссылки) занимают много места. В приведенном ниже примере каждый объект SamsSessionComponent занимает 7 МБ, из которых 2 МБ занимает свойство evalueCpns.

Вышеупомянутым образом мы можем определить, какие объекты занимают много памяти в JVM.