Java снять дамп памяти
В этой статье мы покажем различные способы записи дампа кучи на Java.
Дамп кучи - это снимок всех объектов, находящихся в памяти JVM в определенный момент . Они очень полезны для устранения проблем с утечкой памяти и оптимизации использования памяти в приложениях Java.
Дампы кучи обычно хранятся в файлах hprof двоичного формата. Мы можем открывать и анализировать эти файлы с помощью таких инструментов, как jhat или JVisualVM. Кроме того, для пользователей Eclipse очень часто используется MAT.
В следующих разделах мы рассмотрим несколько инструментов и подходов для создания дампа кучи и покажем основные различия между ними.
2. Инструменты JDK
JDK поставляется с несколькими инструментами для захвата дампов кучи разными способами. Все эти инструменты находятся в папке bin в домашнем каталоге JDK . Следовательно, мы можем запускать их из командной строки, если этот каталог включен в системный путь.
В следующих разделах мы покажем, как использовать эти инструменты для захвата дампов кучи.
2.1. jmap
jmap - это инструмент для вывода статистики о памяти в работающей JVM. Мы можем использовать его для локальных или удаленных процессов.
Чтобы записать дамп кучи с помощью jmap, нам нужно использовать опцию dump :
Наряду с этой опцией мы должны указать несколько параметров:
- live : если установлено, он печатает только те объекты, которые имеют активные ссылки, и отбрасывает те, которые готовы к сборке мусора. Этот параметр не обязателен
- format = b : указывает, что файл дампа будет в двоичном формате. Если не установить, результат будет таким же
- file : файл, в который будет записан дамп
- pid : идентификатор процесса Java
Пример будет таким:
Помните, что мы можем легко получить pid процесса Java с помощью команды jps .
Имейте в виду, что jmap был представлен в JDK как экспериментальный инструмент и не поддерживается. Поэтому в некоторых случаях может быть предпочтительнее использовать вместо этого другие инструменты.
2.2. jcmd
jcmd - это очень полный инструмент, который работает, отправляя запросы команд в JVM. Мы должны использовать его на той же машине, где запущен процесс Java.
Одна из его многочисленных команд - GC.heap_dump . Мы можем использовать его для получения дампа кучи, просто указав pid процесса и путь к выходному файлу:
Мы можем выполнить его с теми же параметрами, что и раньше:
Как и в случае с 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_pid.hprof в каталоге, в котором мы запускаем приложение. Если мы хотим указать другой файл или каталог, мы можем установить его в опции HeapDumpPath :
Когда нашему приложению не хватит памяти с помощью этой опции, мы сможем увидеть в журналах созданный файл, содержащий дамп кучи:
В приведенном выше примере он был записан в файл java_pid12587.hprof .
Как мы видим, эта опция очень полезна, и при запуске приложения с этой опцией нет накладных расходов. Поэтому настоятельно рекомендуется всегда использовать эту опцию, особенно в производственной среде.
Наконец, этот параметр также можно указать во время выполнения с помощью MBean HotSpotDiagnostic . Для этого мы можем использовать JConsole и установить для параметра виртуальной машины HeapDumpOnOutOfMemoryError значение true :
Мы можем найти больше информации о MBeans и JMX в этой статье.
4. JMX
The last approach that we'll cover in this article is using JMX. We'll use the HotSpotDiagnostic MBean that we briefly introduced in the previous section. This MBean provides a dumpHeap method that accepts 2 parameters:
- outputFile: the path of the file for the dump. The file should have the hprof extension
- live: if set to true it dumps only the active objects in memory, as we've seen with jmap before
In the next sections, we'll show 2 different ways to invoke this method in order to capture a heap dump.
4.1. JConsole
The easiest way to use the HotSpotDiagnostic MBean is by using a JMX client such as JConsole.
As shown, we just need to introduce the parameters outputFile and live into the p0 and p1 text fields in order to perform the dumpHeap operation.
4.2. Programmatic Way
The other way to use the HotSpotDiagnostic MBean is by invoking it programmatically from Java code.
To do so, we first need to get an MBeanServer instance in order to get an MBean that is registered in the application. After that, we simply need to get an instance of a HotSpotDiagnosticMXBean and call its dumpHeap method.
Let's see it in code:
Notice that an hprof file cannot be overwritten. Therefore, we should take this into account when creating an application that prints heap dumps. If we fail to do so we'll get an exception:
5. Conclusion
In this tutorial, we've shown multiple ways to capture a heap dump in Java.
Как правило, мы должны помнить об использовании параметра HeapDumpOnOutOfMemoryError всегда при запуске приложений Java. Для других целей можно идеально использовать любые другие инструменты, если мы помним о неподдерживаемом статусе jmap.
В этой статье мы покажем различные способы захвата дампа кучи в Java.
Дамп кучи - это снимок всех объектов в памяти в определенный момент в JVM. Они очень полезны для устранения утечек памяти и оптимизации использования памяти в приложениях Java.
Дампы кучи обычно хранятся в файлах hprof двоичного формата. Мы можем использовать такие инструменты, как jhat или JVisualVM, чтобы открывать и анализировать эти файлы. Кроме того, пользователи Eclipse очень часто используют MAT.
В следующих разделах мы представим несколько инструментов и методов для создания дампов кучи и покажем основные различия между ними.
2.JDK Tools
JDK поставляется с множеством инструментов для захвата дампов кучи разными способами. Все эти инструменты находятся в папке bin в домашнем каталоге JDK. Следовательно, пока этот каталог включен в системный путь, мы можем запускать их из командной строки.
Поэтому мы продемонстрируем, как использовать эти инструменты для захвата дампов кучи.
В следующем разделе мы продемонстрируем, как использовать эти инструменты для захвата дампов кучи.
2.1 jmap
jmap - это инструмент для вывода статистики о памяти в запущенной JVM. Мы можем использовать его для локальных или удаленных процессов. Параметры следующие:
Помимо этой опции, мы также должны указать несколько параметров:
- live: если он установлен, он будет печатать только объекты с активными ссылками и отбрасывать те объекты, которые готовы к сборке мусора. Этот параметр не обязателен
- format-b: указывает, что файл дампа будет в двоичном формате. Если не установлен, результат тот же
- file: файл, в который будет записан дамп
- pid: идентификатор процесса Java
Помните, что мы можем легко получить pid процесса Java с помощью команды jps.
Имейте в виду, что jmap был представлен в качестве экспериментального инструмента в JDK и не поддерживается. Поэтому в некоторых случаях лучше перейти на другие инструменты.
2.2 jcmd
jcmd - это очень полный инструмент, который работает, отправляя запросы команд в JVM. Мы должны использовать его на том же компьютере, на котором запущен процесс Java.
Одна из его многочисленных команд - GC.heap_dump. Нам нужно только указать pid и путь к выходному файлу процесса, а затем мы можем использовать его для получения дампа кучи:
Как и jmap, результирующий дамп имеет двоичный формат.
2.3 JVisualVM
JVisualVM - это инструмент с графическим пользовательским интерфейсом, который позволяет нам отслеживать, устранять неполадки и анализировать приложения Java. Графический интерфейс простой, но очень интуитивно понятный и легкий в использовании.
Один из множества вариантов позволяет нам записывать дампы кучи. Если мы щелкнем правой кнопкой мыши по процессу Java и выберем опцию «Дамп кучи», инструмент создаст дамп кучи и откроет его на новой вкладке:
3. Автоматически записывать дамп кучи
Все инструменты, которые мы показали в предыдущих разделах, предназначены для ручного сбора дампов кучи в определенное время. В некоторых случаях мы хотим получить дамп кучи при возникновении ошибки java.lang.OutOfMemoryError, чтобы помочь нам исследовать ошибку.
В этих случаях Java предоставляет параметр командной строки HeapDumpOnOutOfMemoryError, который создает дамп кучи при возникновении ошибки java.lang.OutOfMemoryError:
По умолчанию он сохраняет дамп в файле java_pid.hprof, который является каталогом, в котором запускается приложение. Если мы хотим указать другой файл или каталог, мы можем установить его в опции HeapDumpPath:
При использовании этой опции, когда приложению не хватает памяти, мы сможем увидеть в файле создания, содержащем дамп кучи:
В приведенном выше примере он записан в файл java_pid12587.hprof.
Как мы видели, эта опция очень полезна, и при запуске приложений с этой опцией нет накладных расходов. Поэтому настоятельно рекомендуется всегда использовать эту опцию, особенно на производстве.
Наконец, вы также можете указать этот параметр во время выполнения с помощью MBean-компонента диагностики точки доступа. Для этого мы можем использовать JConsole иHeapDumpOnOutOfMemoryError Для виртуальной машины установлено значение true:
Последний метод, описанный в этой статье, - использование JMX. Мы будем использовать HotSpotDiagnostic MBean, кратко представленный в предыдущем разделе. Этот MBean предоставляет метод дампа кучи, который принимает 2 параметра:
outputFile: путь к выгружаемому файлу. Файл должен иметь расширение hprof.
live: если установлено значение true, будут сбрасываться только живые объекты в памяти, как мы видели в jmap ранее.
В следующем разделе мы покажем 2 различных способа вызова этого метода для захвата дампа кучи.
4.1 JConsole
Самый простой способ использовать HotSpotDiagnostic MBean - это использовать JMX-клиент (например, JConsole).
Если мы откроем JConsole и подключимся к запущенному процессу Java, мы сможем перейти на вкладку MBeans и найти «HotSpotDiagnostic» в com.sun.management. В действии мы можем найти представленный ранее метод dumpHeap:
4.2 Programmatic Way
Другой способ использования MBean HotSpotDiagnostic - программный вызов из кода Java.
Обратите внимание, что файлы hprof не могут быть перезаписаны. Следовательно, мы должны учитывать это при создании приложений, печатающих дампы кучи. Если мы этого не сделаем, мы получим исключение:
5. Резюме
В этом руководстве мы показали различные способы захвата дампов кучи в Java.
Как правило, мы должны помнить, что всегда следует использовать параметр HeapDumpOnOutOfOfSOnOfOfOfSOnErrorError при запуске приложений Java. Для других целей, если мы помним, что jmap не поддерживается, можно использовать любой другой инструмент.
Утечкой памяти принято называть ситуацию, когда количество занятой памяти в куче растет при длительной работе приложения и не уменьшается после завершения работы Garbage Collector-а. Как известно, память jvm делится на кучу и стек. В стеке кэшируются значения переменных простых типов и ссылок на объекты в разрезе потока, а в куче хранятся сами объекты. Также в куче есть пространство, именуемое Metaspace, где хранятся данные о загруженных классах и данные привязанные к самим классам, а не их экземплярам, в частности, значения статических переменных. Периодически запускаемый java-машиной Garbage Collector (далее GC) находит в куче объекты, на которые больше нет ссылок и освобождает память, занимаемую этими объектами. Алгоритмы работы GC разные и сложные, в частности, при очередном запуске GC не каждый раз «исследует» всю кучу на предмет поиска неиспользуемых объектов, поэтому рассчитывать на то, что какой-либо больше неиспользуемый объект, будет удален из памяти после одного запуска GC не стоит, но если объем памяти, используемой приложением неуклонно растет без видимых причин длительное время, то пора задуматься о том, что могло привести к такой ситуации.
В состав jvm входит многофункциональная утилита Visual VM (далее VM). VM позволяет визуально на графиках наблюдать в динамике ключевые показатели jvm, в частности, объем свободной и занятой памяти в куче, количество загруженных классов, потоков и.т.д. Кроме этого, с помощью VM можно снимать и исследовать дампы памяти. Разумеется, VM позволяет также снимать дампы потоков, и осуществлять профилирование приложения, однако обзор этих функций выходит за рамки данной статьи. Все что нам нужно от VM в данном примере, это подключиться к виртуальной машине и посмотреть для начала на общую картинку использования памяти. Хотелось бы отметить, что для подключения VM к удаленному серверу требуется, чтобы на нем были настроены параметры jmxremote, так как подключение осуществляется через jmx. За описанием данных параметров можно обратиться к официальной документации Oracle или многочисленным статьям на Хабре.
Итак, будем считать, что мы успешно подключились к серверу приложений с помощью VM и взглянем на графики.
На вкладке Heap можно увидеть общий объем и объем занятой памяти jvm. Нужно отметить, что на данной вкладке учитывается и память типа Metaspace (ну, а как иначе, ведь это тоже куча). На вкладке Metaspace отображается информация только по памяти занимаемой метаданными (самими классами и объектами к ним привязанными).
Взглянув на график мы видим, что общий объем памяти heap составляет
10Гб, текущий занятый объем
5.8Гб. Гребни на графике соответствуют вызовам GC, почти прямая линия (без гребней), начиная примерно с 10:18 может (но не обязательно!) говорить о том, что с этого времени сервер приложений почти не работал, так как не было активного выделения и освобождения памяти. Вообще, данный график соответствует нормальной работе сервера приложений (если, конечно, судить о работе только по памяти). Проблемным графиком был бы такой, где прямая горизонтальная синяя линия без гребней, проходила бы примерно на уровне оранжевой, обозначающей максимальный объем памяти в куче.
Теперь взглянем на другой график.
Вот тут мы подходим непосредственно к разбору примера, являющегося основной темой настоящей статьи. На графике Classes отображается количество загруженных в Metaspace классов, и оно составляет
73 тысячи объектов. Хотелось бы обратить внимание, что речь не об экземплярах классов, а о самих классах, то есть объектах типа Class<?>. Из графика не видно, по сколько же экземпляров каждого отдельного типа ClassА или ClassB загружено в память. Возможно, количество одинаковых классов типа ClassA по какой-то причине кратно увеличивается? Должен сказать, что в примере о котором будет рассказано ниже 73000 уникальных классов являлось абсолютно нормальной ситуацией.
Дело в том, что в одном из проектов, в которых принимал участие автор данной статьи, был разработан механизм универсального описания сущностей предметной области (как например в 1С) названный словарной системой, и аналитики, настраивающие систему под конкретного заказчика или под конкретную бизнес область, имели возможность через специальный редактор моделировать бизнес модель создавая новые и изменяя существующие сущности, оперируя не на уровне таблиц, а такими понятиями как «Документ», «Счет», «Сотрудник» и.т.д. Ядро системы создавало для данных сущностей таблицы в реляционной СУБД, причем для каждой сущности могло создаваться несколько таблиц, так как универсальная система позволяла исторично хранить значения атрибутов и еще много чего требующего создания дополнительных служебных таблиц в БД.
Полагаю, что те, кому приходилось работать с ORM-фреймворками уже догадались к чему автор, отвлекся от основной темы статьи на разговор о таблицах. В проекте использовался Hibernate и для каждой таблицы должен был существовать класс Entity-бина. При этом, поскольку, новые таблицы создавалась динамически в процессе работы системы аналитиками, то классы бинов Hibernate генерировались, а не писались вручную разработчиками. И при каждой очередной генерации создавалось около 50-60 тысяч новых классов. Таблиц в системе было значительно меньше (примерно 5-6 тыс), но для каждой таблицы генерировался не только класс Entity-бина, а еще много вспомогательных классов, что в итоге приводило к общей цифре.
Механизм работы был следующий. При старте системы на основании метаданных в БД генерировались классы Entity-бинов и вспомогательные классы (далее просто классы бинов). При работе системы фабрика сессий Hibernate создавала сессии, сессии создавали экземпляры объектов классов бинов. При изменении структуры (добавлении, изменении таблиц) происходила перегенерация классов бинов и создание новой фабрики сессий. После перегенерации новая фабрика создавала новые сессии, которые использовали уже новые классы бинов, старая фабрика и сессии закрывались, а старые классы бинов выгружались GC, так как на них больше не было ссылок из объектов инфраструктуры Hibernate.
В какой-то момент появилась проблема, что количество классов бинов стало увеличиваться после каждой очередной перегенерации. Очевидно, что это происходило из-за того, что старый набор классов, который уже не должен был использоваться, по какой-то причине не выгружался из памяти. Для того чтобы разобраться в причинах такого поведения системы нам пришел на помощь Eclipse Memory Analizer (MAT).
MAT умеет работать с дампами памяти находя в них потенциальные проблемы, но для начала этот дамп памяти нужно получить, а в реальных средах с получением дампа есть определенные нюансы.
Снятие дампа памяти
Как говорилось выше, дамп памяти можно снять непосредственно из VM, нажав кнопку
jmap -dump:live,format=b,file=/tmp/heapdump.bin 14616
Параметр –dump:live крайне важен, так как позволяет существенно сократить его размер, не включая объекты, на которых больше нет ссылок.
Другая распространенная ситуация, это когда снятие дампа вручную не представляется возможным из-за того, что падает сама jvm с OutOfMemoryError. В этой ситуации на помощь приходит опция -XX:+HeapDumpOnOutOfMemoryError и в дополнение к ней -XX:HeapDumpPath, позволяющая указать путь к снятому дампу.
Далее, снятый дамп открываем с помощью Eclipse Memory Analizer. Файл может быть большим по объему (несколько гигабайтов), поэтому надо предусмотреть достаточное количество памяти в файле MemoryAnalyzer.ini:
Локализация проблемы с использованием MAT
Итак, рассмотрим ситуацию, когда количество загруженных классов кратно увеличивается по сравнению с начальным уровнем и не уменьшается даже после принудительного вызова сборки мусора (это можно сделать нажатием соответствующей кнопки в VM).
Выше был концептуально описан процесс перегенерации классов бинов и их использования. На более техническом уровне это выглядело следующим образом:
- Закрываются все Hibernate-сессии (класс SessionImpl)
- Закрывается старая фабрика сессий (SessionFactoryImpl) и обнуляется ссылка на нее из LocalSessionFactoryBean
- Пересоздается ClassLoader
- Обнуляются ссылки на старые классы бинов в классе-генераторе
- Происходит перегенерация классов бинов
Запускаем MAT и открываем полученный ранее файл дампа памяти. После открытия дампа MAT показывает самые большие по объему цепочки объектов в памяти.
После нажатия Leak Suspects видим подробности:
2 сегмента круга по 265 M это 2 экземпляра SessionFactoryImpl. Непонятно почему их 2 экземпляра и, скорее всего, каждый из экземпляров держит ссылки на полный набор классов Entity-бинов. О потенциальных проблемах MAT сообщает нам следующим образом.
Сразу отмечу, что Problem Suspect 3 на самом деле проблемой не является. В проекте был реализован парсер собственного языка, являющегося мультиплатформенной надстройкой над SQL и позволяющего оперировать не таблицами, а сущностями системы, а 121M занимает кэш его запросов.
Вернемся к двум экземплярам SessionFactoryImpl. Нажимаем Duplicate Classes и видим, что действительно каждого класса Entity-бина по 2 экземпляра. То есть ссылки на старые классы Entity-бинов остались и, скорее всего, это ссылки из SesssionFactoryImpl. Судя по исходному коду этого класса ссылки на классы бинов должны храниться в поле classMetaData.
Щелкаем на Problem Suspect 1, далее на класс SessionFactoryImpl и по контекстному меню выбираем List Objects-> With outgouing references. Таким образом мы можем увидеть все объекты на которые ссылается SessionFactoryImpl.
Раскрываем объект classMetaData и убеждаемся, что действительно в нем хранится массив классов Entity-бинов.
Теперь нам нужно понять, что не позволяет сборщику мусора удалить один экземпляр SessionFactoryImpl. Если вернуться к пункту Leak Suspects-> Leaks-> Problem Suspect 1, то мы увидим стек ссылок, который приводит к ссылке на SessionFactoryImpl.
Дело в том, что объекты сессий для определенных целей кэшировались в dbTransactionListeners и перед перегенерацией классов бинов в этом массиве могли оставаться ссылки на них. Сессии, в свою очередь, ссылались на фабрику сессий, а та хранила массив ссылок на все классы бинов. Кроме этого, сессии держали ссылки на экземпляры классов сущностей, а те ссылались на сами классы бинов.
Таким образом, точка входа в проблему была найдена. Ей оказались ссылки на старые сессии из dbTransactionListeners.После того, как ошибка была исправлена и массив dbTransactionListeners стал очищаться проблема была устранена.
Дампы кучи являются жизненно важными артефактами для диагностики проблем, связанных с памятью, таких как медленные утечки памяти, проблемы со сборкой мусора и java.lang. Ошибка памяти. Они также являются жизненно важными артефактами для оптимизации потребления памяти.
Автор оригинала: Ram Lakshmanan.
Дампы кучи являются жизненно важными артефактами для диагностики проблем, связанных с памятью, таких как медленные утечки памяти, проблемы со сборкой мусора и java.lang. Ошибка памяти. Они также являются жизненно важными артефактами для оптимизации потребления памяти.
Существуют отличные инструменты, такие как Eclipse MAT и Герой кучи для анализа свалок кучи. Однако вам необходимо предоставить этим инструментам дампы кучи, записанные в правильном формате и в правильный момент времени.
В этой статье вы найдете несколько вариантов захвата дампов кучи. Однако, на мой взгляд, первые 3 являются эффективными вариантами использования, а другие-хорошими вариантами, о которых следует знать.
1. jmap jmap выводит дампы кучи в указанное расположение файла. Этот инструмент упакован в JDK. Его можно найти в папке \bin.
Вот как вы должны вызвать карту:
1 jmap,файл=/opt/tmp/heapdump.bin 37320
2. Ошибка в памяти Когда приложение работает на java.lang. Из-за ошибки памяти, идеально захватить дамп кучи прямо в этот момент, чтобы диагностировать проблему, потому что вы хотите знать, какие объекты находились в памяти и какой процент памяти они занимали, когда java.lang. Произошла ошибка памяти. Однако из-за жары момента, в большинстве случаев, ИТ/операционная группа забывает захватить дамп кучи. Мало того, они также перезапускают приложение. Чрезвычайно сложно диагностировать какие-либо проблемы с памятью без захвата дампов кучи в нужное время.
Лучшая практика: Всегда сохраняйте это свойство настроенным во всех приложениях, так как вы никогда не знаете, когда произойдет ошибка OutOfMemoryError.jcmd3.
3. инструмент jcmd jcmd используется для отправки запросов диагностических команд в JVM. Он упакован как часть JDK. Его можно найти в папке \bin.
Вот как вы должны вызвать cmd:
1 jcmd 37320 GC.heap_dump/opt/tmp/heapdump.бен
4. JVisualVM JVisualVM-это средство мониторинга и устранения неполадок, которое упаковано в JDK. Когда вы запускаете этот инструмент, вы можете видеть все процессы Java, запущенные на локальном компьютере. Вы также можете подключиться к процессу java, запущенному на удаленном компьютере, с помощью этого инструмента.
Инжир: Захват дампа кучи из JVisualVM
Рис.: Использование Java Mission Control в качестве клиента JMX для создания дампа кучи
6. Программный подход Вместо использования инструментов вы также можете программно захватывать дампы кучи из приложения. Могут быть случаи, когда вы захотите захватить дампы кучи на основе определенных событий в приложении. Вот хорошая статья от Oracle , в которой приводится исходный код для захвата дампов кучи из приложения путем вызова компонента MBean JMX, который мы обсуждали в описанном выше подходе.
7. Административная консоль IBM Если ваше приложение запущено на IBM Websphere Application Server, вы можете использовать административную консоль для создания куч.
1.Запустите административную консоль 2.In в области навигации выберите Устранение неполадок > дампы и ядра Java 3.Выберите имя сервера, для которого вы хотите создать дамп кучи 4.Нажмите Дамп кучи, чтобы создать дамп кучи для указанного сервера
Дампы кучи являются жизненно важными артефактами для диагностики проблем, связанных с памятью, таких как медленные утечки памяти, проблемы сбора мусора и java.lang.OutOfMemoryError. Они также являются жизненно важными артефактами для оптимизации потребления памяти.
Есть отличные инструменты, такие как Eclipse MAT и Heap Hero для анализа дампов кучи. Однако вам необходимо предоставить этим инструментам дампы кучи, записанные в правильном формате и правильном моменте времени.
Эта статья дает вам несколько вариантов захвата дампов кучи. Однако, по моему мнению, первые 3 являются эффективными вариантами использования, а другие являются хорошими вариантами, о которых следует знать.
1. Jmap
Jmap печати кучи дампов в указанном месте файла. Этот инструмент упакован в JDK. Его можно найти в папке bin .
Вот как вы должны вызвать jmap:
pid: is the Java Process Id, whose heap dump should be captured file-path: is the file path where heap dump will be written in to.
1 | jmap -dump: format = b, file = / opt / tmp / heapdump.bin 37320 |
Примечание: очень важно пропустить «живой» вариант. Если эта опция пропущена, в файл дампа кучи записываются только живые объекты в памяти. Если эта опция не пропущена, все объекты, даже те, которые готовы к сборке мусора, печатаются в файле дампа кучи. Это значительно увеличит размер файла дампа кучи. Это также сделает анализ утомительным. Чтобы устранить проблемы с памятью или оптимизировать память, достаточно просто «живой» опции.
2. HeapDumpOnOutOfMemoryError
Когда приложение испытывает java.lang.OutOfMemoryError, идеально было бы захватить дамп кучи прямо в этот момент, чтобы диагностировать проблему, потому что вы хотите знать, какие объекты находились в памяти и какой процент памяти они занимали при возникновении java.lang.OutOfMemoryError. Однако из-за высокой температуры в большинстве случаев ИТ-специалисты забывают захватить дамп кучи. Мало того, они также перезапускают приложение. Диагностировать проблемы с памятью крайне сложно без своевременного захвата дампов кучи.
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/tmp/heapdump.binЧитайте также: