Автор оригинала: Marcos Lopez Gonzalez.
1. Введение
В этой статье мы покажем различные способы захвата свалки кучи на Java.
Свалка кучи является моментальным снимком всех объектов, которые находятся в памяти в JVM в определенный момент . Они очень полезны для устранения проблем с утечкой памяти и оптимизации использования памяти в Java-приложениях.
Куча свалок, как правило, хранятся в файлах hprof двоичного формата. Мы можем открывать и анализировать эти файлы с помощью таких инструментов, как jhat или JVisualVM. Кроме того, для пользователей Eclipse очень часто используется MAT .
В следующих разделах мы пройдемся по нескольким инструментам и подходам для создания свалки кучи и покажем основные различия между ними.
2. Инструменты JDK
JDK поставляется с несколькими инструментами для захвата кучи свалок по-разному. Все эти инструменты расположены под бен папка внутри домашнего каталога JDK . Таким образом, мы можем начать их с командной строки до тех пор, пока этот каталог включен в системный путь.
В следующих разделах мы покажем, как использовать эти инструменты для захвата кучи свалок.
2.1. jmap
jmap является инструментом для печати статистики о памяти в запущенной JVM. Мы можем использовать его для локальных или удаленных процессов.
Чтобы захватить кучу свалки с помощью jmap мы должны использовать свалка выбор:
jmap -dump:[live],format=b,file=
Наряду с этой опцией следует указать несколько параметров:
- живые : Если установить его только печатает объекты, которые имеют активные ссылки и отбрасывает те, которые готовы к сбору мусора. Этот параметр является необязательным
- формат’b : указывает, что файл дампа будет в двоичном формате. Если не установить результат, то тот же
- файл : файл, в котором будет написана свалка
- пид : идентификатор процесса Java
Примером может быть:
jmap -dump:live,format=b,file=/tmp/dump.hprof 12587
Помните, что мы можем легко получить пид Java-процесса с помощью JPS команда.
Имейте в виду, что jmap был представлен в JDK в качестве экспериментального инструмента, и это не поддерживается. Поэтому в некоторых случаях может быть предпочтительнее использовать вместо этого другие инструменты.
2.2. jcmd
jcmd является очень полным инструментом, который работает, отправив командные запросы на JVM. Мы должны использовать его в той же машине, где работает процесс Java.
Одной из его многочисленных команд является GC.heap_dump . Мы можем использовать его, чтобы получить кучу свалки, просто указав пид процесса и пути вывода файла:
jcmdGC.heap_dump
Мы можем выполнить его с теми же параметрами, которые мы использовали раньше:
jcmd 12587 GC.heap_dump /tmp/dump.hprof
Как и в случае с jmap, сгенерированная свалка находится в двоичном формате.
2.3. JVisualVM
JVisualVM является инструментом с графическим пользовательским интерфейсом, который позволяет нам контролировать, устранение неполадок и профили Java приложений . Графический интерфейс прост, но очень интуитивно понятен и прост в использовании.
Один из его многочисленных вариантов позволяет нам захватить кучу свалки. Если мы нажимаем правой кнопкой мыши на процесс Java и выбираем “Свалка” опция, инструмент создаст кучу свалки и открыть его в новой вкладке:
Обратите внимание, что мы можем найти путь файла, созданного в “Основная информация” секция.
Начиная с JDK 9, Visual VM не входит в дистрибутивы Oracle JDK и Open JDK. Поэтому, если мы используем Java 9 или более новые версии, мы можем получить JVisualVM от Visual VM с открытым исходным кодом сайт проекта .
3. Захват свалки кучи автоматически
Все инструменты, которые мы показали в предыдущих разделах, предназначены для захвата кучи свалок вручную в определенное время. В некоторых случаях, мы хотим получить кучу свалки, когда java.lang.OutOfMemoryError происходит так, что это помогает нам исследовать ошибку.
В этих случаях Java предоставляет HeapDumpOnOutOfMemoryError опция командной строки, генерируемая свалкой кучи при java.lang.OutOfMemoryError брошен:
java -XX:+HeapDumpOnOutOfMemoryError
По умолчанию он хранит свалку в java_pid
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=
Когда у нашего приложения заканчивается память с помощью этой опции, мы сможем увидеть в журналах созданный файл, содержащий свалку кучи:
java.lang.OutOfMemoryError: Requested array size exceeds VM limit Dumping heap to java_pid12587.hprof ... Exception in thread "main" Heap dump file created [4744371 bytes in 0.029 secs] java.lang.OutOfMemoryError: Requested array size exceeds VM limit at com.baeldung.heapdump.App.main(App.java:7)
В приведеном выше примере она была написана java_pid12587.hprof файл.
Как видим, этот вариант очень полезен и нет накладных расходов при запуске приложения с этой опцией. Поэтому рекомендуется использовать эту опцию всегда, особенно в производстве.
Наконец, эта опция также может быть указана во время выполнения с помощью HotSpotДиагностик МБин . Для этого мы можем использовать JConsole и установить HeapDumpOnOutOfMemoryError Вариант VM для истинное :
Мы можем найти более подробную информацию о MBeans и JMX в этой статье .
4. JMX
Последний подход, который мы будем охватывать в этой статье является использование JMX. Мы будем использовать HotSpotДиагностик МБин что мы кратко представили в предыдущем разделе. Этот MBean обеспечивает свалкаХап метод который принимает 2 параметра:
- выходFile : путь файла для свалки. Файл должен иметь расширение hprof
- живые : если установлен на самом деле он сбрасывает только активные объекты в памяти, как мы видели с jmap раньше
В следующих разделах мы покажем 2 различных способа вызова этого метода, чтобы захватить свалку кучи.
4.1. JConsole
Самый простой способ использовать HotSpotДиагностик MBean с помощью JMX клиента, таких как JConsole.
Если мы откроем JConsole и подключиться к запущенной Java-процессу, мы можем перейти к MBeans вкладке и найти HotSpotДиагностик под com.sun.management . В операциях мы можем найти свалкаХап метод, который мы описали ранее:
Как показано, нам просто нужно ввести параметры выходFile и живые в p0 и p1 текстовые поля для выполнения свалкаХап операция.
4.2. Программный путь
Другой способ использования HotSpotДиагностик MBean, ссылаясь на него программно из Java-кода.
Для этого нам сначала нужно получить MBeanServer например, для того, чтобы получить MBean, который зарегистрирован в заявке. После этого нам просто нужно получить экземпляр HotSpotDiagnosticMXBean и назвать его свалкаХап метод .
Давайте посмотрим его в коде:
public static void dumpHeap(String filePath, boolean live) throws IOException { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy( server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); mxBean.dumpHeap(filePath, live); }
Обратите внимание, что файл hprof не может быть перезаписана. Поэтому следует учитывать это при создании приложения, которое печатает свалки кучи. Если мы этого не сделаем, мы получим исключение:
Exception in thread "main" java.io.IOException: File exists at sun.management.HotSpotDiagnostic.dumpHeap0(Native Method) at sun.management.HotSpotDiagnostic.dumpHeap(HotSpotDiagnostic.java:60)
5. Заключение
В этом учебнике мы показали несколько способов захвата свалки кучи на Java.
Как правило, мы должны помнить, чтобы использовать HeapDumpOnOutOfMemoryError опция всегда при запуске Java-приложений. Для других целей, любой из других инструментов может быть прекрасно использован до тех пор, как мы держим в виду неподдерживаемый статус jmap.
Как всегда, полный исходный код примеров доступен более на GitHub .