Ниже приведен один из примеров анализа дампа кучи, чтобы узнать, какие объекты ответственны за нехватку памяти 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.