Перейти к содержимому

Heap dump java как снять

  • автор:

Различные способы захвата дампов кучи Java

В этом руководстве мы рассмотрим различные способы захвата дампа кучи в Java.

Дамп кучи — это снимок всех объектов, находящихся в памяти JVM в определенный момент . Они очень полезны для устранения проблем с утечкой памяти и оптимизации использования памяти в приложениях Java.

Дампы кучи обычно хранятся в файлах hprof двоичного формата. Мы можем открывать и анализировать эти файлы с помощью таких инструментов, как jhat или JVisualVM. Кроме того, пользователи Eclipse очень часто используют MAT .

В следующих разделах мы рассмотрим несколько инструментов и подходов к созданию дампа кучи и покажем основные различия между ними.

2. Инструменты JDK​

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

В следующих разделах мы рассмотрим, как использовать эти инструменты для захвата дампов кучи.

2.1. jmap​

jmap — это инструмент для вывода статистики о памяти в работающей JVM. Мы можем использовать его для локальных или удаленных процессов.

Чтобы захватить дамп кучи с помощью jmap, нам нужно использовать параметр дампа :

jmap -dump:[live],format=b,file=

Наряду с этой опцией мы должны указать несколько параметров:

  • live : если установлено, печатаются только объекты, имеющие активные ссылки, и отбрасываются те, которые готовы к сборке мусора. Этот параметр является необязательным.
  • format=b : указывает, что файл дампа будет в двоичном формате. Если не установлено, результат тот же.
  • file : файл, в который будет записан дамп
  • pid : идентификатор процесса Java

Пример будет выглядеть так:

jmap -dump:live,format=b,file=/tmp/dump.hprof 12587 

Помните, что мы можем легко получить pid процесса Java с помощью команды jps .

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

2.2. jcmd​

jcmd — очень полный инструмент, который работает, отправляя командные запросы в JVM. Мы должны использовать его на той же машине, где запущен процесс Java.

Одна из его многочисленных команд — GC.heap_dump . Мы можем использовать его для получения дампа кучи, просто указав pid процесса и путь к выходному файлу:

jcmd GC.heap_dump 

Мы можем выполнить его с теми же параметрами, что и раньше:

 jcmd 12587 GC.heap_dump /tmp/dump.hprof 

Как и в случае с jmap, созданный дамп имеет двоичный формат.

2.3. JVisualVM​

JVisualVM — это инструмент с графическим пользовательским интерфейсом, который позволяет нам отслеживать, устранять неполадки и профилировать приложения Java . Графический интерфейс простой, но очень интуитивно понятный и простой в использовании.

Один из его многочисленных вариантов позволяет нам захватить дамп кучи. Если мы щелкнем правой кнопкой мыши процесс Java и выберем опцию «Дамп кучи» , инструмент создаст дамп кучи и откроет его на новой вкладке:

./7b944a9466d2376d30272b2550a8faaa.png

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

Начиная с 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.hprof в каталоге, где мы запускаем приложение. Если мы хотим указать другой файл или каталог, мы можем установить его в опции HeapDumpPath :

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.foreach.heapdump.App.main(App.java:7) 

В приведенном выше примере он был записан в файл java_pid12587.hprof .

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

Наконец, этот параметр также можно указать во время выполнения с помощью HotSpotDiagnostic MBean . Для этого мы можем использовать JConsole и установить для параметра виртуальной машины HeapDumpOnOutOfMemoryError значение true :

./c68c0470a4be8da49f2f78a4e800e70b.png

Дополнительную информацию о MBeans и JMX мы можем найти в этой статье .

4. ДжМХ​

Последний подход, который мы рассмотрим в этой статье, — это использование JMX. Мы будем использовать HotSpotDiagnostic MBean , кратко представленный в предыдущем разделе. Этот MBean предоставляет метод dumpHeap , который принимает два параметра:

  • outputFile : путь к файлу дампа. Этот файл должен иметь расширение hprof.
  • live : если установлено значение true, он выгружает только активные объекты в памяти, как мы видели ранее с jmap.

В следующих разделах мы покажем два разных способа вызова этого метода для захвата дампа кучи.

4.1. JConsole ​

Самый простой способ использовать HotSpotDiagnostic MBean — использовать клиент JMX, например JConsole.

Если мы откроем JConsole и подключимся к запущенному процессу Java, мы сможем перейти на вкладку MBeans и найти HotSpotDiagnostic в разделе com.sun.management . В операциях мы можем найти описанный ранее метод dumpHeap :

./29c05b269be2a3a6bbf6ef5b34d27212.png

Как показано, нам просто нужно ввести параметры outputFile и live в текстовые поля p0 и p1 , чтобы выполнить операцию dumpHeap .

4.2. Программный способ​

Другой способ использования MBean HotSpotDiagnostic — программный вызов его из кода Java.

Для этого нам сначала нужно получить экземпляр MBeanServer , чтобы получить MBean, зарегистрированный в приложении. После этого нам просто нужно получить экземпляр HotSpotDiagnosticMXBean, и вызвать его метод dumpHeap .

Давайте посмотрим на это в коде:

 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 .

Диагностика OutOfMemoryError подручными средствами

Один мой коллега является адептом философии “дефолтных настроек”. Эта философия пропагандирует следующий подход: не пытайтесь менять environment под свои нужды, — просто научитесь пользоваться стандартным environment’ом.

Несмотря на то что сам по себе этот подход довольно спорен, в нем есть свои плюсы. Умение решать задачи штатными средствами особенно выручает когда необходимо быстро продиагностировать какую-то проблему, а у вас под рукой нет настроенного environment’а. Например, вы временно работаете за другой машиной, или географически отдалены от вашего милого сердцу, прекрасно настроенного environment’а. Поэтому, я считаю, очень важно уметь диагностировать типовые проблемные ситуации пользуясь только штатными утилитами. Так что давайте посмотрим как мы можем диагностировать memory leak’и в java, когда у вас под рукой нет ничего кроме JDK.

Итак, в логах вы нашли OutOfMemoryError . Что делать? Во-первых, надо уяснить чего делать не надо. Ни в коем случае не надо перезапускать процесс. Сделав это вы потеряете весь heap приложения, а в нашем случае heap — это единственная улика, которая может натолкнуть вас на причины OOM. Вам надо сделать heap dump. Это позволит понять кто занимает память, а также почему эта память не была конкретно высвобождена garbage collector’ом.

Самый простой способ сделать dump — это использовать утилиту jmap из пакета JDK.

$ jmap -dump:format=b,file=heap-dump.hprof $PID 

Вот теперь, когда вы сделали dump, вы можете смело возвращать систему к жизни и перезапускать JVM, если это требуется.

Перед доставкой dump’а на вашу машину советую его пережать, так как heap dump’ы очень хорошо жмутся. Когда dump будет на вашей машине возникает вопрос. А каким образом вообще понять что там у “не внутря”?

С последними версиями JDK поставляется приложение VisualVM, которое содержит в себе в том числе и memory profiler. Загружаем heap dump в VisualVM и открываем вкладку “Classes”.

Распределение памяти по классам

На этой вкладе мы видим распределение памяти в dump’е по классам объектов. В данном случае большего всего памяти занимает тип char[] . Видимо кто-то хранит много строчек в памяти. Кто же это?

Дважды щелкаем на типе и переходим в instance view. Здесь мы видим все экземпляры данного типа, а также кто на них ссылается, а следственно и то, почему GC их не собрал. Просматриваем несколько экземпляров.

Путь к GC-root’ам

В моем случае большинство ссылок на строку удерживается базой данных H2 при помощи soft reference. Немного погуглив можно узнать, что H2 использует soft reference для хранения кеша базы данных. Отличительной особенностью soft ссылок является то, что JVM собирает их только тогда, когда ей не хватает памяти (перед генерацией OOM). Это делает soft ссылки довольно удобным механизмом для различного рода кешей. Тем не менее JVM не гарантирует что она успеет собрать все soft ссылки перед генерацией exception’а. Что, судя по всему, и происходит в моем случае.

Также стоит отметить, что VisualVM может сам находить ближайших GC root, удерживающий данный instance от garbage collector’а.

Show Nearest GC root

Это избавляет вас от необходимости сайгаком прыгать по дереву referent’ов в поисках ближайшего GC root’а.

Auto dump Link to heading

Иногда бывает так, что причиной OutOfMemoryError служит не нехватка памяти, а другие причины. Например, если JVM видит, что она тратит большую часть процессорного времени на сборку мусора, а не на выполнение собственно приложения, она генерирует следующий exception.

java.lang.OutOfMemoryError: GC overhead limit exceeded 

В зависимости от того как написано приложение оно может остаться живо, и даже продолжать выполнять свои функции. Причем уже через несколько минут heap может быть чистенький и без лишнего мусора (GC не зря жрал так много процессорного времени, и в конце концов собрал весь мусор).

Отладка затрудняется, — у вас нет heap’а, хоть на кофейной гуще гадай. В этом случае, стоит перезапустить приложение с ключом -XX:-HeapDumpOnOutOfMemoryError . Это заставит JVM сделать heap dump автоматически перед тем как кидать в бедное приложение OOM’ом. После следующего подобного инцидента у вас появится пища для размышлений.

Runtime статистика Link to heading

Часто бывает так, что у программиста появляется теория относительно того, почему возникает memory leak. Например, зная список последних изменений кодовой базы, можно предположить что проблема локализована в каком-то конкретном участке системы. В этом случае, вам снова может помочь jmap. Эта утилита позволяет просмотреть количество экземпляров и занимаемую ими память по типам.

$ jmap -histo $PID | egrep "(#instances|---|java.util.LinkedList)" num #instances #bytes class name ---------------------------------------------- 110: 506 20240 java.util.LinkedList$Entry 166: 220 8800 java.util.LinkedList 1021: 5 240 java.util.LinkedList$ListItr 

Вы также можете легко посчитать суммарную память занимаемую типами определенного пакета.

$ jmap -histo $PID | grep "org.netbeans" | awk ' END ' 1745.28K 

Да пребудет с вами сила дефолтных настроек.

Анализ дампа кучи Java: разбираем на примерах

image

Я увлекаюсь управлением памятью в Java и в этой статье попробую объяснить, как взять и проанализировать дамп кучи – разберём на примерах. Но для начала давайте вспомним, что известно об этой предметной области. Немного освежив теорию, мы возьмем дамп кучи и проанализируем, каким он получится в простом приложении.

❯ Что такое куча?

Всякий раз, когда вы создаете объект, он хранится в области памяти, которая в приложениях для JVM называется «куча». Как вы уже догадались, объем кучи ограничен, и «кто-то» должен хранить объекты в куче. Этот инструмент называется сборщиком мусора ( Garbage Collector ). Сборщик мусора подбирает в куче неиспользуемые объекты, после чего уничтожает их в соответствии с определённым алгоритмом, так, чтобы в куче всегда имелась свободная память.

Но, как только всё свободное место в куче будет израсходовано, вы получите:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

Сборщик мусора подбирает только те объекты, на которые нет ссылок, но иногда это могут быть и объекты со ссылками, но такие, которые вообще не применяются в приложении. Такая практика всегда приводит к утечке памяти в приложении. Чтобы обнаружить такую проблему и понять, что происходит в куче, мы выводим дамп кучи. Давайте рассмотрим, как сделать дамп кучи для конкретного приложения.

❯ Захват дампа кучи

Если вы читали статью об анализе дампа потоков Java, то рассматриваемая в этом разделе тема с захватом дампа кучи вам уже знакома. Чтобы вы смогли самостоятельно собрать дамп кучи, приведу здесь пример. Те же команды вы можете выполнять у себя на компьютере; подобные примеры встречаются в Gradle. В этой статье я покажу 3 типа захвата дампа кучи; VisualVM, jmap и автоматический дамп кучи с опциями JVM. Давайте постепенно разберём каждый из методов, но сначала скопируйте проект с примером.

О проекте

Вышеупомянутый тренировочный проект можно скопировать здесь. Перейдя в папку heapdumpanalysis, вы найдёте следующие классы в каталоге java source.

package com.huseyin.heapdumpanalysis; import java.util.ArrayList; import java.util.List; import lombok.extern.slf4j.Slf4j; @Slf4j public class ProductCatalogService < public ListgetProducts(int limit) < Listproducts = new ArrayList<>(); for (int i = 0; i < limit; i++)< products.add(new String(new char[1024*1000])); // 1 MB string >return products; > >

Этот класс предназначен для генерации списка продуктов (на самом деле это просто строки), и каждый продукт имеет размер 1 МБ. А вот второй класс:

package com.huseyin.heapdumpanalysis; import java.util.Arrays; import java.util.List; public class HeapDump < public static void main(String[] args) throws InterruptedException < int count = Integer.parseInt(args[0]); int waitTime = Integer.parseInt(args[1]); System.out.println("Loading products. "); Listproducts = new ProductCatalogService().getProducts(count); System.out.println(products.size() + " products are loaded into memory."); Thread.sleep(waitTime * 1000L); > >

Он нужен для запуска приложения, чтобы сгенерировать список продуктов. Класс будет потреблять память в том количестве, которое вы зададите в аргументах команды Gradle следующим образом.

JAVA_TOOL_OPTIONS=-Xmx200m \ ./gradlew :heapdumpanalysis:run \ -PmainClass=com.huseyin.heapdumpanalysis.HeapDump \ --args="180 30"

В JAVA_TOOL_OPTIONS можно указать аргументы JVM, в соответствии с которыми Gradle мог бы подобрать и использовать эти аргументы во время операции ветвления JVM. В нашем случае мы указываем -Xmx200m; что означает, что максимальная емкость кучи будет 200 МБ. Более того, если вы ссылаетесь на объекты размером > ~ 200 МБ, то получите исключение java.lang.OutOfMemoryError , и приложение завершит работу. Я использовал ~ 200 МБ, поскольку куча также содержит некоторые классы из среды выполнения Java, и то пространство в 200 МБ (JRE Classes) – вот и весь объём для объектов в вашем приложении.

—args — это список аргументов, которые мы можем прочитать из java-приложения с помощью args[0], и здесь в первом пункте указывается размер продуктов. Например, мы генерируем 180 продуктов, то есть, 180 МБ данных (1М для каждого продукта). Второй аргумент — время ожидания в секундах. 30 означает, что как только приложение сгенерирует продукты, оно будет ждать 30 секунд до завершения выполнения. Это нужно, чтобы вы могли получить дамп кучи запущенного приложения. Теперь, когда мы знаем, как выполнить приложение, давайте посмотрим, как можно снять дамп кучи с помощью Visual VM.

Снятие дампа кучи с помощью VisualVM

VisualVM — это инструмент с GUI, сочетающий инструменты командной строки JDK и обеспечивающий удобное профилирование. Инструмент мет использоваться как на стадии разработки, так и в продакшене.

Главная страница Visual VM

Скачав Visual VM отсюда, вы cможете просмотреть запущенные приложения JVM. Откройте VisualVM и проверьте их следующим образом:

image

Стартовый экран Visual VM

Как только вы откроете приложение, запущенное после выполнения в Gradle, можно будет просмотреть его метаданные. Перейдите во вкладку Monitor, где выводится использование кучи.

image

Использование кучи

Синий участок на диаграмме — это используемая часть кучи, а коричневый — память кучи, доступная для вашего приложения. Если нужно вывести дамп кучи, нажмите Heap Dump в правом верхнем углу страницы Monitor. Вы увидите еще одно окно со сведениями о дампе кучи, как показано ниже.

image

Сведения о дампе кучи – 1

image

Сведения о дампе кучи – 2

  1. Можно просмотреть в агрегированном виде некоторые данные о размере, количестве классов, экземплярах и т. д.
  2. Здесь Visual VM показывает, сколько экземпляров каждого типа класса у нас имеется. Видим, что в данном приложении больше всего экземпляров у byte[].
  3. В этом разделе выводится каждый экземпляр и его размер. Как видите, размер каждого файла — 1024 байта, всего получается 1 МБ, это наш продукт.
  4. Эта часть содержит информацию о рабочем окружении вашего компьютера и о дистрибутиве java.
  5. Похож на раздел 2, но на этот раз с упорядочиванием по размеру экземпляров, а не по их количеству.

Снятие дампа кучи с помощью jmap

Программа jmap поставляется с дистрибутивом JDK. С её помощью можете получить дамп кучи, сначала найдя идентификатор процесса JVM, а затем сняв дамп кучи следующим образом.

image

Список процессов JVM

Теперь для снятия дампа кучи выполним:

jmap -dump:live,file=/tmp/heapdump.hprof 49417

Так удастся снять дамп кучи и сохранить результаты в /tmp/heapdump.hprof. Здесь команда jmap снимает дамп кучи, для этого мы задаём опцию –dump. Также мы собираемся взять только живой объект с помощью опции :live. Вдобавок jmap принимает параметр file для сохранения результатов в указанном месте. Наконец, принимается идентификатор процесса JVM для анализа кучи. Что же дальше? Что мы будем делать с этим файлом heapdump.hprof? Этот файл не составит труда загрузить в VisualVM следующим образом.

image

Загрузить

image

Только файлы hprof

Остальные операции точно такие же, как рассмотренные в предыдущем разделе.

В VisualVM удобно выполнять элементарные операции, но мне ещё нравится инструмент MAT (Eclipse Memory Analyzer). Он также заслуживает отдельной статьи, описывающей best practices :). С документацией по этому инструменту можно ознакомиться здесь.

Автоматический анализ дампа кучи

Во всех примерах, рассмотренных выше, собирали дамп кучи вручную. Однако на практике такой подход может оказаться нецелесообразным по следующим причинам;

  • У вас могут быть десятки и сотни приложений JVM
  • Возможно, уже произошёл аварийный останов приложения
-XX:+HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath=/tmp/heapdump.hprof

Применительно к нашему приложению, можно использовать следующую команду Gradle.

JAVA_TOOL_OPTIONS="-Xmx200m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof" \ ./gradlew :heapdumpanalysis:run \ -PmainClass=com.huseyin.heapdumpanalysis.HeapDump \ --args="210 30"

Поскольку мы предоставляем кучу объёмом 200MB и пытаемся сгенерировать список товаров общим объемом 210MB , в результате получим OutOfMemoryError , и JVM выведет дамп имеющейся кучи, затем сохранит его в файле /tmp/heapdump.hprof

image

Автоматический анализ дампа кучи

Особенно при работе с облачно-нативными системами, где JVM-процесс контейнеризован (в микросервисных системах могут насчитываться десятки и сотни контейнеров), разумно было бы сконфигурировать этот параметр для автоматического создания дампа кучи. Однако необходимо смонтировать специальный каталог, прикрепив его к этим контейнерам, иначе файл с результатами дампа кучи исчезнет из контейнера после перезапуска этого контейнера.

❯ Заключение

Важно обеспечить хорошую отслеживаемость процесса JVM, чтобы понять, как он протекает в вашем приложении. Чтобы понять, как это происходит, можно обратить внимание на кучу, где находятся все java-объекты. Мы используем методы снятия дампа кучи, и можно выбрать один или несколько таких методов при работе в имеющейся экосистеме приложений JVM.
Если хотите склонировать проект, рассмотренный в этой статье – он находится здесь.

  • Блог компании Timeweb Cloud
  • JavaScript
  • Java

Java Heap Dump: Вы готовы к задаче?

Если у вас такой же энтузиазм, как и у меня по поводу производительности Java, анализ дампа кучи не должен быть для вас загадкой. Если это так, то хорошей новостью является то, что у вас есть возможность улучшить свои навыки устранения неполадок Java и знания JVM.

В настоящее время JVM эволюционировала до такой степени, что сегодня гораздо проще генерировать и анализировать дамп кучи JVM по сравнению со старым JDK 1.0 – JDK 1.4 дня.

Анализ дампа кучи не следует рассматривать как замену инструментов профилирования и анализа JVM, таких как JProfiler или Plumbr, но дополняющих друг друга. Это особенно полезно при устранении утечек памяти кучи Java и проблем java.lang.OutOfMemoryError.

Этот пост предоставит вам обзор дампа кучи JVM и того, что от него ожидать. Он также предоставит рекомендации о том, как и когда вы должны тратить время на анализ дампа кучи. Будущие статьи будут включать учебники по самому процессу анализа.

Обзор дампа кучи Java

Дамп кучи JVM – это, по сути, «снимок» кучи памяти Java в данный момент времени. Он сильно отличается от дампа потоков JVM, который является снимком потоков.

Такой снимок содержит низкоуровневую информацию о Java-объектах и ​​классах, размещенных в куче Java, таких как:

  • Java-объекты, такие как Class, поля, примитивные значения и ссылки
  • Данные, относящиеся к загрузчику классов, включая статические поля (важно для проблем с утечкой из загрузчика классов)
  • Корни или объекты сборки мусора, доступные вне кучи (системные загрузчики загрузочных классов, такие как rt.jar, JNI или собственные переменные, потоки, локальные Java-объекты и т. Д.)
  • Данные и стеки, связанные с потоками (очень полезно для внезапного увеличения кучи Java, особенно в сочетании с анализом дампа потоков)

Обратите внимание, что обычно рекомендуется создавать дамп кучи после полного GC, чтобы исключить ненужный «шум» от объектов, на которые нет ссылок.

Анализ зарезервирован для Элиты?

За последние 10 лет, работая с группами поддержки производства, я заметил одно распространенное заблуждение, что у «элиты» или поставщика продукта зарезервировано такое задание для более глубокого анализа, как профилирование, анализ дампа кучи или потока дампа (Oracle, IBM…) ,

Я не мог не согласиться больше.

Как разработчик Java, вы пишете код, потенциально работающий в среде с высокой степенью параллелизма, управляющей сотнями и сотнями объектов в JVM. Вы должны беспокоиться не только о проблемах параллелизма, но также о сборке мусора и занимаемой памяти вашего приложения. Вы находитесь в лучшем положении, чтобы выполнить этот анализ, так как вы являетесь экспертом приложения.

Ниже приведены типичные вопросы, на которые вы сможете ответить:

  • Сколько параллельных потоков необходимо для одновременного запуска моего приложения в соответствии с прогнозом нагрузки? Сколько памяти потребляет каждый активный поток, прежде чем они выполнят свои задачи?
  • Какова площадь статической памяти моего приложения? (библиотеки, размер загрузчика классов, структуры данных кэша в памяти и т. д.)
  • Какова динамическая память моего приложения под нагрузкой? (следы сессий и т. д.)
  • Вы профилировали свое приложение для любой утечки памяти?

Нагрузочное тестирование, профилирование вашего приложения и анализ дампов кучи Java (например, захваченных во время нагрузочного тестирования или производственной проблемы) позволят вам ответить на поставленные выше вопросы. После этого вы сможете достичь следующих целей:

  • Снизить риск проблем с производительностью после внедрения производства
  • Увеличьте ценность своей работы и своего клиента, предоставив дополнительные указания и факты для команды по производству и управлению производительностью; позволяя им принимать надлежащие меры по улучшению ИТ
  • Проанализируйте основную причину утечек памяти или проблем, которые влияют на производственную среду вашего клиента.
  • Совершенствуйте свои технические навыки, изучая эти принципы и методы анализа производительности
  • Повысьте навыки работы с JVM, улучшив понимание JVM, сборки мусора и жизненных циклов объектов Java

Последнее, чего вы хотите достичь – это умение «плато». Если вы не удовлетворены этим типом анализа, то мои рекомендации приведены ниже:

  • Попросите более старшего члена вашей команды выполнить анализ дампа кучи и отследить его работу и подход
  • Как только вы почувствуете себя более комфортно, предложите себе выполнить тот же анализ (из другого проблемного случая) и на этот раз попросите более опытного сотрудника отследить вашу аналитическую работу
  • В конце концов студент (вы) станет наставником

Когда использовать

Анализ дампов кучи JVM не следует выполнять каждый раз, когда вы сталкиваетесь с проблемой кучи Java, такой как OutOfMemoryError. Поскольку этот процесс анализа может занять много времени, я рекомендую этот анализ для следующих сценариев:

  • Необходимость понимания и настройки вашего приложения и / или окружающего API или самого контейнера Java EE.
  • Устранение неполадок с утечкой памяти в куче Java
  • Утечки памяти загрузчика классов Java
  • Внезапные проблемы кучи Java увеличивают проблемы или вызывают события (должны быть объединены с анализом дампа потока в качестве отправной точки)

Теперь найдите ниже некоторые ограничения, связанные с анализом дампа кучи:

  • Генерация дампа кучи JVM – это интенсивная вычислительная задача, которая будет зависать на вашей JVM до завершения. Надлежащая должная осмотрительность необходима, чтобы уменьшить влияние на вашу производственную среду
  • Анализ дампа кучи не даст вам полного следа памяти процесса Java, например, собственной кучи. Для этого вам нужно будет полагаться на другие инструменты и команды ОС для этой цели
  • У вас могут возникнуть проблемы с открытием и анализом дампов кучи, созданных из более старых версий JDK, таких как 1.4 или 1.5.

Методы генерации дампов кучи

Дампы кучи JVM обычно создаются в результате двух действий:

  • Автоматически генерируется или срабатывает в результате java.lang.OutOfMemoryError (например, Java Heap, PermGen или истощение собственной кучи)
  • Генерируется вручную с использованием таких инструментов, как jmap, VisualVM (через JMX) или команда уровня ОС

# Автоматически запускаемые дампы кучи

Если вы используете HotSpot Java VM 1.5+ или JRockit R28 +, то вам потребуется добавить следующий параметр ниже при запуске JVM:

-XX:+HeapDumpOnOutOfMemoryError

Приведенный выше параметр позволит виртуальной машине HotSpot автоматически генерировать дамп кучи после события OOM. Формат дампа кучи для этих типов JVM – HPROF (* .hprof).

Если вы используете IBM JVM 1.4.2+, генерация дампа кучи в результате события OOM включена по умолчанию. Формат дампа кучи для IBM JVM – PHD (* .phd).

# Запущенные вручную дампы кучи

Ручная генерация дампов кучи JVM может быть достигнута как показано ниже:

  • Использование jmap для HotSpot 1.5+
  • Рекомендуется использовать VisualVM для HotSpot 1.6+ *

** Пожалуйста, сделайте все возможное, чтобы обеспечить должную осмотрительность для вашей производственной среды, поскольку создание дампа кучи JVM – это навязчивый процесс, который повредит ваш процесс JVM до завершения **

Если вы используете IBM JVM 1.4.2, вам потребуется добавить следующие переменные среды при запуске JVM:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *