дамп это что в программировании

Что такое дампы как это работает в программировании

Что такое дампы как это работает в программировании

Похожие статьи

13 comments on “ Что такое дампы как это работает в программировании ”

Дамп — это слитая программатором прошивка с какого либо устройства (микроконтроллер, память EEPROM, память Flash…)

Михаил, я правильно понял что дамп это прошивка управления каким либо устройством которая хранится в микросхеме флэш памяти

Алексей, да, правильно, но не обязательно во флеш памяти. Например, основная программа хранится во флеш, а данные для работы устройства в EEPROM. Хороший пример современная стиральная машина. Например, модуль Evo 2. У него основная программа хранится во флеш, а данные(сколько раз крутнуть барабаном, когда включить тэн, когда слить воду и тд) хранятся в отдельно стоящей от основного микроконтроллера EEPROM памяти.

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

Алексей, что значит прописывать?

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

Алексей, это пишет программист. В самом коде пишется, куда нужно отправится программе, если соблюдены определенные условия. Например, тот же самый биос перед основным запуском материнской платы сначала проверяет переферию материнской платы, и если ошибок не возникло во время проверки, то отдается команда на загрузку операционной системы с жёсткого диска или с юсб накопителя. Если во время проверки возникнет какая либо ошибка, например, видеокарта не работает, то биос остановит процесс загрузки и выдаст код ошибки, например, зуммером.

Источник

Дамп памяти

Дамп памяти (англ. memory dump ; в Unix — core dump ) — содержимое рабочей памяти одного процесса, ядра или всей операционной системы. Также может включать дополнительную информацию о состоянии программы или системы, например значения регистров процессора и содержимое стека. Многие операционные системы позволяют сохранять дамп памяти для отладки программы. Как правило, дамп памяти процесса сохраняется автоматически когда процесс завершается из-за критической ошибки (например, из-за ошибки сегментации). Дамп также можно сохранить вручную через отладчик или любую другую специальную программу.

Содержание

История

Английский термин core dump буквально переводится как «распечатка содержимого сердечников»: на ранних компьютерах, дамп означал принтерную распечатку содержимого памяти на магнитных сердечниках (англ. magnetic core memory ).

В Unix

В современных Unix-подобных операционных системах дамп памяти сохраняется в виде файла, который обычно называется core или core. ; его формат такой же, как формат исполняемых файлов этой ОС (ELF в Linux и современных Unix, a.out в традиционных Unix-системах, Mach-O в Mac OS X). Для анализа core-файла используется отладчик (например gdb) или инструмент objdump.

В Windows

В Windows, аналогом core dump’а является minidump, который позволяет сохранить частичную или полную информацию о процессе, в том числе и полное содержимое рабочей памяти.

Дамп системы

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Дамп содержит данные и команды различных процессов, как пользовательских приложений так и ядра операционной системы (в частности все прерывания BIOS, они же стандартные функции). Также в дампе содержатся значения регистров процессора и содержимое различных стеков, системное время и другие переменные среды.

См. также

Ссылки

Форматы дампа памяти в различных операционных системах:

Полезное

Смотреть что такое «Дамп памяти» в других словарях:

дамп памяти — рампа памяти — [http://www.iks media.ru/glossary/index.html?glossid=2400324] Тематики электросвязь, основные понятия Синонимы рампа памяти EN memory dump … Справочник технического переводчика

ДАМП ПАМЯТИ — Копия содержимого оперативной памяти на внешнем носителе (бумаге, магнитном диске и т. п.) Словарь бизнес терминов. Академик.ру. 2001 … Словарь бизнес-терминов

ДАМП — 1. Распечатка содержимого памяти ЭВМ или файла, обычно без учета внутренней структуры данных. Копия содержимого регистров, нужного участка оперативной памяти, блока данных или файла выводится на печать последовательно, байт за байтом, в форме… … Словарь бизнес-терминов

Дамп — В Викисловаре есть статья «дамп» Дамп (англ. dump «мусорная куча, свалка; выбрасывать, вываливать») снимок инф … Википедия

дамп — Данные, представляющие собой полное или частичное содержимое оперативной памяти, выводимое на периферийное устройство. [ГОСТ 19781 90] дамп свалка аварийное снятие сброс Данные, получаемые в результате разгрузки памяти и используемые для поиска… … Справочник технического переводчика

ДАМП — ДАМП, в вычислительной технике информация, скопированная из памяти компьютера на выходное или записывающее устройство. Это может быть целый файл, перенесенный на другой диск, или текст, отправленный на печать прямо с экрана (экранный дамп) … Научно-технический энциклопедический словарь

дамп — а; м. Спец. Данные, полученные при разгрузке памяти компьютера или переводимые из одного запоминающего устройства в другое … Энциклопедический словарь

Дамп — 55. Дамп Dump Данные, представляющие собой полное или частичное содержимое оперативной памяти, выводимое на периферийное устройство Источник: ГОСТ 19781 90: Обеспечение систем обработки информации программное. Термины и определения … Словарь-справочник терминов нормативно-технической документации

дамп — а; м.; спец. Данные, полученные при разгрузке памяти компьютера или переводимые из одного запоминающего устройства в другое … Словарь многих выражений

Отладчик использования памяти — (англ. memory debugger) инструментальное программное обеспечение для обнаружения утечек памяти и переполнений буфера. Это происходит из за ошибок, связанных с выделением и освобождением динамической памяти. Программы, написанные на… … Википедия

Источник

Как анализировать Thread Dump

В программе курса Разработчик Java довольно много тем, посвященных внутренностям работы JVM. Мы разбираемся в механизмах работы коллекций, байт-кода, сборщика мусора и т.д. Сегодня предлагаем Вашему внимаю перевод довольно интересной статьи о thread dump-е. Что это такое, как его получить и как использовать.

Хотите узнать, как анализировать thread dump (дамп потоков)? Заходите под кат, чтобы узнать больше о том как в Java получить thread dump и что с ним потом делать.

Большинство современных Java-приложений являются многопоточными. Многопоточность может существенно расширить функционал приложения, в то же время она вносит существенную сложность.

В однопоточном приложении все ресурсы (разделяемая память, операции ввода/вывода и т.д.) могут использоваться без синхронизации, т.к. в любой момент времени только один поток пользуется ресурсом.

В случае многопоточных приложений необходимо найти компромисс между усложнением программы и возможным повышением производительности, когда несколько потоков могут использовать все доступные (часто больше одного) ядра центрального процессора (CPU). Если сделать все правильно, то используя многопоточность (формализована в Amdahl’s Law), можно добиться существенного прироста производительности приложения. Однако при этом надо помнить об обеспечении синхронного доступа нескольких потоков к разделяемому ресурсу. В большинстве случаев, фреймворки, такие как Spring, инкапсулируют работу с потоками и скрывают от пользователей многие технические детали. Однако и в случае применения современных сложных фреймворков что-то может пойти не так, и мы, как пользователи, столкнемся со сложно решаемыми багами многопоточности.

К счастью, Java оснащена специальным механизмом для получения информации о текущем состоянии всех потоков в любой момент времени — это thread dump (своего рода моментальный снимок). В этой статье мы изучим, как получить thread dump для приложения реалистичных размеров и как этот dump проанализировать.

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

Основная терминология

С первого взгляда Java thread dump-ы могут показаться «китайской грамотой», ключом к ее понимаю являются следующие понятия. В общем, давайте, повторим основные термины многопоточности, которые будем использовать для анализа дампов.

У каждого потока есть уникальный идентификатор и имя. Потоки могут быть «демонами» и «не демонами».

Программа завершает свою работу, когда завершаются все потоки «не демоны» или вызывается метод Runtime.exit. Работающие «демоны» не влияют на завершение работы программы. Т.е. JVM ждем когда доработают все «не демоны» и завершает работу, на «не демонов» не обращает внимание.

За более подробной информацией обращайтесь к документации класса Thread.
Поток может находится в одном из следующих состояний:

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

Более детальную информацию можно найти в этих источниках:

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

Создание примера программы

Прежде, чем создать thread dump, нам надо разработать Java-приложение. Традиционный «hello, world!» для нашей цели слишком прост, а дамп среднего размера приложения может оказаться слишком сложным для демонстрации. Исходя из этого, мы создадим достаточно простое приложение, в котором создаются два потока. Причем потоки попадают в deadlock:

Эта программа создает два ресурса: resourceA и resourceB, и стартует два потока: threadLockingResourceAFirst и threadLockingResourceBFirst, которые блокируют ресурсы друг друга.

Причиной возникновения deadlock-а является «перекрестная» блокировка ресурсов потоками.

Причиной возникновения deadlock является попытка «взаимного» захвата ресурсов, т.е. поток threadLockingResourceAFirst захватывает ресурс resourceA, поток threadLockingResourceBFirst захватывает ресурс resourceB. После этого поток threadLockingResourceAFirst, не отпуская свой ресурс, пытается захватить resourceB, а поток threadLockingResourceBFirst, не отпуская свой ресурс, пытается захватить ресурс resourceA. В результате потоки блокируются. Задержка в 1с добавлена, чтобы гарантировать возникновение блокировки. Потоки ждут освобождение нужных ресурсов, но это никогда не случится.

Вывод программы будет таким (числа после java.lang.Object@ будут разные для каждого запуска):

После вывода этих сообщений программа будет выглядеть как работающая (процесс, выполняющий эту программу, не завершен), при этом программа не выполняет никакой работы. Вот так вот и выглядит deadlock на практике. Чтобы решить проблему, нам надо вручную создать tread dump и проанализировать состояние потоков.

Генерация Thread Dump

На практике, Java-программа может аварийно завершиться и при этом создать thread dump. Однако в ряде случаев (например в случае deadlock-ов), программа не завершается и thread dump не создает, она просто зависает. Для создания дампа таких зависших программ, прежде всего надо выяснить идентификатор процесса программы, т.е. Process ID (PID). Для этого можно воспользоваться утилитой JVM Process Status (JPS), которая начиная с версии 7, входит в состав Java Development Kit (JDK). Чтобы найти PID процесса нашей зависшей программы, мы просто выполним jps в терминале (Windows или Linux):

Первая колонка — это идентификатор локальной виртуальной машины (Local VM ID, т.е. lvmid) для выполняемого Java-процесса. В контексте локальной JVM, lvmid указывает на PID Java-процесса.

Надо отметить, что это значение, скорее всего, будет отличаться от значения выше. Вторая колонка — это имя приложения, которое может указывать на имя main-класса, jar-файла или быть равно «Unknown». Все зависит от того, как приложение было запущено.

Полученный файл thread_dump.txt содержит thread dump нашей зависшей программы и содержит важную информацию для диагностики причин возникновения deadlock-а.

В нашем случае вызов будет такой:

Анализ простого Thread Dump

Открыв файл thread_dump.txt, мы увидим примерно следующее содержание:

Introductory Information

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

В первой строке указывается время, когда дамп был сформирован, во второй — диагностическая информация о JVM, на которой дамп был получен:

В этой секции нет информации о потоках. Тут задается общий контекст системы, в которой был собран дамп.

Общие сведенья о потоках

В следующей секции представлена информация о потоках, которые выполнялись в системе в момент сбора дампа:

В следующей секции приводится список:

В нем содержится информация о потоках за пределами JVM, т.е. это не потоки виртуальной машины и не потоки сборщика мусора. Если посмотреть на адреса этих потоков, то можно заметить, что они соответствуют значению tid — «естественному, железному» (native) адресу в операционной системе, а не Thread ID.

Троеточия используются для сокрытия излишней информации:

Потоки

Сразу после блока SMR следует список потоков. Первый поток в нашем списке — Reference Handler:

Краткое описание потока

В первой строке для каждого потока приводится общее описание. Описание содержит следующие пункты:

РазделПримерОписание
Name«Reference Handler»Человеко-читаемое имя потока. Имя можно задать, вызвав метод setName объекта Thread. А получить через вызов getName
ID#2Уникальный ID, присвоенный каждому объекту класса Thread. ID генерируется для потоков в системе. Первоначальное значение 1. Каждому вновь созданному потоку присваивается свой ID, предварительно увеличенный на 1. Это свойство потока «только для чтения», может быть получено с помощью функции getId объекта класса Thread.
Daemon statusdaemonФлаг является признаком того, что поток является демоном. Если это демон, то флаг будет выставлен. Например, поток Thread-0 не демон
Priorityprio=10Числовой приоритет Java-потока. Обратите внимание, что этот приоритет не обязательно соответствует приоритету связанного потока в операционной системе. Для установки приоритета можно
воспользоваться методом setPriority объекта класса Thread, а для получения
методом getPriority.
OS Thread Priorityos_prio=2Приоритет потока в операционной системе. Этот приоритет может отличаться от того, который присвоен связному Java-потоку.
Addresstid=0x00000250e4979000Адрес Java-потока. Этот адрес представляет собой указатель на Java Native Interface (JNI) нативный объект класса Thread (объект C++ Thread который связан с Java-потоком через JNI). Это значение получается путем приведения указателя на this
(объекта C++, который связан с этим Java-потоком) к integer. См.
строку 879 в hotspot/share/runtime/thread.cpp:

Хотя ключ для этого объекта (tid) может быть похож на ID-потока,
на самом деле, это адрес связного объекта JNI C++ Thread, и это не то значение, которое
возвращает метод getId Java-объекта Thread.

OS Thread IDnid=0x3c28Уникальный идентификатор потока операционной системы, к которому привязан Java-поток.
Это значение выводится следующим кодом:
строка 42 в hotspot/share/runtime/osThread.cpp:

Statuswaiting on conditionЧеловеко-читаемый статус текущего потока.
Эта строка выводит дополнительную информацию к простому статусу потока (см.ниже), которая может быть
использована для понимания, что поток собирался делать (т.е. пытался ли поток получить блокировку
или ждал выполнения условия разблокирования).
Last Known Java Stack Pointer[0x000000b82a9ff000]Последний известный указатель на стек (SP), ассоциированный и данным потоком.
Это значение получается с использованием нативного кода С++, перемешанного с кодом Java с использованием JNI. Значение возвращает функция last_Java_sp(),
строка 2886 в hotspot/share/runtime/thread.cpp:

Для простых thread dump-ов эта информация практически бесполезна. Однако в сложных случаях SP может
быть использован для отслеживания блокировок.

Состояние потока

Вторая строка — это текущее состояние потока. Возможные состояния потока приведены в enum:
Thread.State:

NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED

Более подробную информацию смотрите в документации.

Thread Stack Trace

Следующая секция содержит stack trace потока в момент снятия дампа. Этот stack trace очень похож на stack trace, который формируется не перехваченным исключением. И содержит имена классов и строк, которые выполнялись в момент формирования дампа. В случае потока Reference Handler мы не видим ничего интересного.

Однако в трассировке потока Thread-02 есть кое-что интересное, отличное от стандартного трейса:

В трассировке мы видим, что добавилась информация о блокировке. Этот поток ожидает блокировку на объекте с адресом 0x00000000894465b0 (тип объекта java.lang.Object). Более того поток сам удерживает блокировку с адресом 0x00000000894465a0 (тоже объект java.lang.Object). Эта информация нам пригодится далее для диагностики deadlock-а.

Захваченные примитивы синхронизации (Ownable Synchronizer)

В последней секции приводится список примитивов синхронизации (synchronizers), захваченных потоком. Это объекты, которые могут быть использованы для синхронизации потоков, например, защелки (locks).

В соответствии с официальной документацией Java, Ownable Synchronizer — это наследники AbstractOwnableSynchronizer (или его подкласса), которые могут быть эксклюзивно захвачены потоком для целей синхронизации.

ReentrantLock и write-lock, но не read-lock класса ReentrantReadWriteLock — два хороших примера таких «ownable synchronizers», предлагаемых платформой.

Для получения более подробной информации по этому вопросу можно обратиться к этому
посту.

Потоки JVM

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

Глобальные ссылки JNI

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

В большинстве простых случаев эта информация не используется. Однако важность глобальных ссылок надо понимать. Более подробную информацию смотрите в этом посте.

Взаимно заблокированные (Deadlocked) потоки

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

В первом подразделе описывается сценарий взаимной блокировки (deadlock):

Поток Thread-0 ожидает возможность захватить монитор (это обращение к блоку synchronized(secondResource) в нашем приложении), в то же время этот поток удерживает монитор, который пытается захватить поток Thread-1 (это обращение к тому же фрагменту кода: synchronized(secondResource) в нашем приложении).

Эта циклическая блокировка по другому называется deadlock. На рисунке ниже
эта ситуация представлена в графическом виде:

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Во втором подразделе для обоих заблокированных потоков приведен stack trace.

Этот stack trace позволяет нам проследить за работой каждого потока до появления блокировки.
В нашем случае, если мы посмотрим на строку:

at DeadlockProgram$DeadlockRunnable.run(DeadlockProgram.java:34), то увидим проблемный участок кода:

Эта строка является первой строкой блока synchronized, который является причиной блокировки, и подсказывает нам, что синхронизация на secondResource и является причиной взаимной блокировки. Чтобы исправить ситуацию, мы должны обеспечить в обоих потоках одинаковый порядок синхронизации на ресурсах resourceA и resourceB. Если мы сделаем это, то придем к следующему приложению:

Это приложение завершится без взаимной блокировки, и в качестве результата мы получим следующий вывод (обратите внимание на то, что адреса экземпляров класса Object изменились):

В результате, используя только информацию, полученную из thread dump, мы смогли найти причину и исправить взаимную блокировку в нашем приложении. Предложенная техника достаточна для большинства простых приложений (или приложений с небольшим количеством deadlock-ов). Чтобы разобраться с более сложными ситуациями, потребуются другие методы.

Анализ более сложных Thread Dump-ов

Дампы настоящих приложений могут быть очень большими и сложными.

В одной JVM одновременно могут быть запущены сотни тысяч потоков. И заблокированными могут оказаться больше чем два потока (или может быть несколько проблем многопоточности, вызванных одной проблемой).

Анализ такого громадного объема информации может стать настоящей проблемой.

Для анализа больших дампов предназначены специальные утилиты-анализаторы — Thread Dump Analyzers (TDAs). Эти утилиты парсят Java thread dump-ы и выводят информацию в человеко-читаемом виде, часто с применением графических средств. Более того, некоторые из них могут выполнить статический анализ и найти причину проблемы. Конечно, выбор конкретной утилиты зависит от целого ряда обстоятельств.

Тем не менее приведем список наиболее популярных TDA:

Заключение

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

В этой статье мы разработали приложение с deadlock, сформировали дамп зависшего приложения. Проанализировали дамп и нашли причину блокировки и исправили её. Это не всегда так просто, для анализа большинства реальных приложений очень полезно использовать специальные утилиты — анализаторы.

Тем не менее, каждый профессиональный Java-разработчик должен понимать основы анализа thread dump-ов. Должен ориентироваться в их структуре, знать какую информацию можно извлечь и как ее использовать для решения проблем многопоточности.

Хотя, thread dump — это не «серебряная пуля» в мире многопоточности, тем не менее это важное средство диагностирования сложных, но довольно распространенных проблем многопоточных Java-приложений.

В программе курса Разработчик Java вопросы многопоточности занимают заметную часть. Мы детально рассматриваем как разрабатывать программы так, чтобы не приходилось по ночам разбираться с deadlock-в продакшене.

Как всегда интересны ваши мнения и комментарии, которые можно оставить тут или заглянуть к Виталию на день открытых дверей.

Источник

Всё, что вы хотели знать о стек-трейсах и хип-дампах. Часть 2

Всё, что вы хотели знать о стек-трейсах и хип-дампах. Часть 1
Перед вами вторая часть расшифровки доклада Андрея Паньгина aka apangin из Одноклассников с одного из JUG’ов (допиленная и расширенная версия его доклада с JPoint 2016). В этот раз мы закончим разговор о стек-трейсах, а также поговорим о дампах потоков и хип-дампах.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

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

Сколько пройдет вызовов, прежде чем появится StackOverflowError (при стандартном размере стека)?
Давайте измерим:

Тот же самый код, только добавили catch StackOverflowError.
На 64-битной системе с размером стека 1 Мб результат варьируется от 22 до 35 тыс. вызовов. Почему такая большая разница? Дело в JIT: методы компилируются в фоновом потоке компилятора параллельно с исполнением java-кода. В какой-то момент (после того, как метод recursion несколько раз уже вызвался) запускается компиляция этого метода, а в это время продолжается исполнение в интерпретаторе. Как только компилятор закончит свою работу, следующий вызов перейдет в скомпилированный код.

Начиная с Java 8, у нас по умолчанию в одной VM есть 2 компилятора — «легкий» C1 и «тяжелый» C2, т.е. возможна ситуация, когда у нас на стеке окажутся фреймы трех типов: интерпретированный, скомпилированный C1 и скомпилированный C2. Размер фрейма может сильно отличаться. У интерпретатора самые громоздкие фреймы, потому что все хранится на стеке (все аргументы, локальные переменные, указатель текущего байткода и т.д.). В скомпилированном коде многое из этого не нужно и, чем оптимальнее будет компилятор, тем меньше надо хранить на стеке. C2, к примеру, вообще не будет заводить место на стеке под локальные переменные — все распихает по регистрам, а еще и заинлайнит на один уровень.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Если тот же самый код исполнить в чисто интерпретируемом режиме с ключиком

-Xint

Результат — практически всегда 12500 (± несколько фреймов).
Теперь то же самое, но после компилятора C1.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

По умолчанию на 64-битной архитектуре размер стека 1 Мб, но его можно корректировать. Эти 2 ключика — синонимы.

Thread(ThreadGroup, target, name, stackSize)

Но при создании больших стеков нельзя забывать о том, что они занимают место в памяти и может случиться такая ситуация, что много потоков с большим размером стека приведут к out of memory:

Минимальный размер стека на 64-битной системе — примерно 228 Кб (он может меняться от версии к версии JDK). Как устроен стек и откуда складывается этот минимальный размер?

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

На стеке, помимо фреймов ваших Java-методов, есть еще некоторое зарезервированное пространство. Это как минимум всегда 1 красная зона (размером с 1 страницу — 4 Кб) в самой верхушке стека и несколько страниц желтой зоны.

Красная и желтая зоны нужны для проверки stack overflow. В начале обе зоны защищены от записи. Каждый Java-метод через попытку записи по адресу текущего стек-поинтера проверяет достижение красной или желтой зоны (при попытке записи операционная система генерирует исключение, которое виртуальная машина перехватывает и обрабатывает). При достижении желтой зоны она разблокируется, чтобы хватило места запустить обработчик stack overflow, и управление передается на специальный метод, который создает экземпляр StackOverflowError и передает его дальше. При попадании в красную зону возникает unrecoverable error и виртуальная машина фатально завершается.

Есть еще так называемая shadow-зона. У нее довольно странный размер: на Windows — 6 страниц, на Linux, Solaris и прочих ОС — 20 страниц. Это пространство резервируется для нативных методов внутри JDK и нужд самой виртуальной машины.

Когда я готовил презентацию, запускал свой рекурсивный тестик и на Java 8, и на Java 9. На последней я получил такой чудесный краш виртуальной машины (фрагмент вывода):

#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x0000019507acb5e0, pid=9048, tid=10544
#
# JRE version: Java(TM) SE Runtime Environment (9.0+119) (build 9-ea+119)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (9-ea+119, mixed mode, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# J 155 C2 demo4.Recursion.recursion()V (12 bytes) @ 0x0000019507acb5e0 [0x0000019507acb5e0+0x0000000000000000]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
.

Я, естественно, скачал самый последний из доступных билдов (на момент доклада это был 9.0+119), на нем эта проблема также воспроизводится.
Это очень хороший случай для анализа краш-дампа (Андрей Паньгин — Анализ аварийных дампов JVM). Тут пригодились все навыки, в частности, дизассемблирование.
Вот инструкция, которая записывает значение относительно текущего стек-поинтера. Краш произошел как раз на этой инструкции:

Instructions:
00000000: 89 84 24 00 a0 ff ff mov DWORD PTR [rsp-0x6000],eax
00000007: 55 push rbp
00000008: 48 83 ec 10 sub rsp,0x10
0000000c: 49 ba 78 71 88 8d 00 00 00 00 movabs r10,0x8d887178
00000016: 41 83 42 70 02 add DWORD PTR [r10+0x70],0x2
0000001b: e8 e0 ff ff ff call 0x00000000

Java Threads:
=>0x0000019571d71800 JavaThread «main» [_thread_in_Java, >
stack(0x0000007632e00000,0x0000007632f00000)]
0x0000007632e00ff8

Используя значение регистра RSP, можно вычислить адрес, в который мы записываем. Нужно отнять 6000 в HEX от этого адреса, получится какое-то такое значение:

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Мы записываем по этому значению. Там же в краш-дампе указан диапазоны стека текущего потока:

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Мы видим, что это значение попадает в конец самой первой (самой верхней) страницы этого стека, т.е. как раз в красную зону.

Действительно, есть такой баг. Я проанализировал его и нашел причину: некоторым функциям JVM не хватает на Windows доступных 6 shadow-страниц (они занимают больше при исполнении). Разработчики виртуальной машины обсчитались.
Кстати, размер этих зон можно менять ключиками JVM.

Зачем нам вообще большие стеки? Для Java EE, не иначе.
Вот одна из моих любимых картинок на эту тему.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

На 2 строчки бизнес-логики порождаются сотни фреймов от различных фреймворков и application-серверов.

Стек-трейсы для измерения перформанса

Профилирование — неотъемлемая часть измерения производительности вашей системы. Все профиляторы можно разделить на 2 большие группы: семплирующие и инструментирующие.
Инструментирующий профайлер просто помечает методы: добавляет в начало какую-то сигнализацию о входе в метод, в конец — сигнализацию о выходе из него. Понятно, если мы каждый метод так проинструментируем, все это будет создавать большой overhead, хотя измерение будет довольно точным.

В продакшене чаще всего применяется иной подход — семплирующий профайлер. Он с какой-то периодичностью (10-100 раз в секунду) снимает дамп потоков и смотрит, какие треды с какими трейсами в данный момент выполняются. Методы, которые чаще всего попадают в эти стек-трейсы, и являются горячими.

Давайте посмотрим сразу на примере, как это работает. Я написал небольшую программку. Несмотря на то, что она маленькая, сходу и не скажешь, что в ней может тормозить.
Во-первых, она генерирует 2 случайные географические координаты. Потом в цикле вычисляет расстояние от случайно сгенерированной координаты до другой заданной точки (Москвы) — т.е. есть функция distanceTo, в которой много математики.
Результаты складываются в хэш-мап.

Все это в цикле много-много раз бежит:

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

Возьму Java VisualVM (входит в стандартную поставку JDK — ничего проще нет), нахожу наш процесс на закладке Sampler, щелкаем CPU — начинаем измерения (дадим поработать пол минуты). Дефолтный интервал измерений — раз в 100 мс.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Чуть менее чем полностью (согласно профилятору Java VisualVM) время у нас тратится на IdentiryHashMap.put.

Если посмотреть плоскую табличку по методам, отсортировав по SelfTime:

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Как будто ничего другого и не выполняется.
То же самое можно померить другими профайлерами (JProfiler, YourKit и т.п.), уверяю вас, результат будет такой же.

Неужели HashMap настолько тормозные? Нет. Просто профайлеры врут.
Устроены они при этом одинаково: с заданной периодичностью они через JMX или JVMTI вызывают метод, который получает дамп всех потоков. Например, в JVMTI есть метод GetAllStackTraces. То, что виртуальная машина говорит, они здесь суммируют и печатают.

Положа руку на сердце, это не профайлеры врут, а JVM — она дает неправильные стек-трейсы. У всех профайлеров есть одна большая проблема: стек-трейсы потоков могут быть сняты только в моменты safepoint, а это определенные точки в коде, про которые виртуальная машина знает, что поток можно безопасно остановить. И таких точек на самом деле немного: они есть внутри циклов и в точках выхода из методов. Если у вас есть большое полотно кода — той же математики; без циклов — в нем может вообще не быть safepoint, значит, это полотно никогда в стек-трейсы не попадет.

Другая проблема в том, что потоки, которые спят, и потоки, которые работают, сэмплятся одинаково, т.к. у нас снимается дамп со всех потоков. Это не очень хорошо, т.к. спящие потоки нам не интересно видеть в стек-трейсах.

Также большинство профайлеров не могут отличить нативные методы, которые спят на каком-то блокирующем системном вызове. Например, при ожидании данных из сокета поток будет в состоянии RUNNABLE и профайлер будет показывать, что поток ест 100% CPU. А он не ест CPU, просто виртуальная машина не может отличить работающий нативный метод от блокирующего системного вызова.

В ОС предусмотрены возможности для профилирования нативного кода. Если говорить о Linux, там есть системный вызов setittimer, который задает таймер и с заданной периодичностью генерирует специальный сигнал ОС (SIGPROF) для профилирования. Получать его будет тот тред, который в данный момент исполняется. Нам бы хорошо уметь использовать возможности ОС и в обработчике сигнала SIGPROF собирать стек-трейсы текущего потока, даже если он не в safepoint. И в виртуальной машине HotSpot такая возможность предусмотрена. Есть недокументированный приватный API: AsyncGetCallTrace, который можно вызывать для получения текущего стека потоков не в safepoint.
Эта дырка была пропилена специально для Oracle Developer Studio. Это чуть ли не единственный профилятор, который получает честный стек-трейс.
Пока готовил этот доклад, я смотрел, а есть ли кто-то еще, кто использует эти методы. Нашел буквально 2 проекта: один — старый и уже заброшенный, а другой появился сравнительно недавно (в 2015 году) и называется honest-profiler.

API здесь довольно простой: подготавливаем место, куда будем складывать стек, и вызываем метод:

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Третьим параметром этого метода является текущий контекст, который приходит к нам в signal handler.

Ссылка на мой собственный open source профайлер: https://github.com/apangin/async-profiler. Берите — пользуйтесь. Сейчас он уже в том состоянии, когда его не стыдно показать людям. Правда, сейчас он реализован только для Linux (Примечание: со времени доклада добавилась поддержка macOS).

Проверим на том же примере.
Говорим, какой процесс профилируем.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Наш pid — 3202.
Особенность моего профайлера (которую я еще ни у кого не видел) в том, что он может подключаться на лету (упомянутый honest-profiler надо обязательно запускать в качестве Java-агента при старте приложения).

Дадим несколько секунд на профилирование. Вот что получаем в результате:

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

В конце — плоский список методов; чуть выше — отдельно подробности (все стеки потоков). Картина кардинально отличается. Чуть ли не треть всего времени уходит на математику — вычисление расстояния. IdentityHashMap.put — вообще внизу с результатом 2% (согласно первому профайлеру он занимал 100%). А реально занимает время вычисление identityHashCode объекта. И немало времени уходит на сам put и resize. К слову, генерация случайной локации тоже не бесплатна (как минимум 12%).
Почувствуйте разницу.

Накладные расходы этого профайлера гораздо меньше. Его можно запускать хоть 1000 раз в секунду, и это будет нормально, поскольку он снимает стек-трейс только активного потока. И складывает результаты он в очень компактную структуру — он не генерирует все эти названия методов, классов. Это все вычисляется только при распечатке. А во время профилирования складываются только jmethodID (фактически, указатели на методы).

Дампы потоков

Есть много способов делать дампы потоков: из Java кода или из натива, изнутри самого процесса или снаружи.
Если говорить об анализе процесса изнутри, то есть Java API getAllStackTraces, который выдает нам массив StackTraceElement со всеми вытекающими.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Когда мы на продакшене пытались им пользоваться, для случая с 2 тысячами потоков, у каждого из которых глубина стека 50-60 фреймов, один только этот массив занимал порядка 50 Мб.
Есть похожий метод у JMX (он полезен тем, что его можно дергать удаленно). Он выдает тот же самый массив StackTraceElement, а вдобавок еще информацию о захваченных мониторах.

Если говорить о генерации стек-трейсов из самого приложения, гораздо лучше способ — JVMTI (Tool Interface) — нативный интерфейс для разработки инструментов, профилировщиков, анализаторов и т.д.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Есть метод GetAllStackTraces, который обычно используют как раз профайлеры. По сравнению с Java API у него очень компактное представление.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Преимущество метода в том, что стек-трейсы распечатает сама Java машина. Это делается с максимальной скоростью. Это все равно происходит во время safepoint, но нам не нужно создавать никаких промежуточных структур.
Альтернативный путь — утилита jstack. Она работает через механизм dynamic attach (на ней я остановлюсь подробнее).

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

После того как соединение по UNIX socket установлено, утилита посылает команду, и эту команду исполняет сама виртуальная машина, а ответ пересылает назад утилите по этому же сокету.

В Window все устроено несколько по-другому (не знаю, почему нельзя было сделать так же; в Windows нет разве что UNIX-сокетов, зато есть named pipes) — есть другой красивый API, который мне нравится, поэтому я не мог не упомянуть его здесь.

Начало примерно такое же — создается named pipe. Далее в Windows API есть функция WriteProcessMemory, которая может записывать некоторые данные напрямую в память чужого процесса, если у нее есть на это права. Через эту функцию создается временная вспомогательная страница памяти в адресном пространстве java-процесса, туда записывается команда, которую нужно выполнить, аргументы и название pipe, куда пойдет ответ. Еще одна не менее чудесная функция, которая позволяет внедрить в чужой процесс тред — CreateRemoteThread. Утилита jstack запускает удаленный поток — он исполняется уже в контексте процесса виртуальной машины. И в качестве аргумента этому треду передается указатель на созданную ранее область памяти, где есть вся информация о команде.

Далее все то же самое: JVM сама исполняет команду и посылает результат назад.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Плюсы такого подхода:

Виртуальная машина поддерживает следующие команды:

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Это дамп тредов, дамп хипа, получение гистограммы хипа, распечатка и установка флагов виртуальной машины, исполнение команд, которые умеет исполнять утилита jcmd, и load — наверное, самая интересная команда, которая позволяет загрузить библиотеку JVMTI-агента в удаленную виртуальную машину. С помощью команды load и работает мой async профайлер (загружает свою библиотеку в удаленную JVM).

Кратко продемонстрирую, как это работает. Запущу какой-нибудь процесс, допустим, tomcat.
pid процесса — 8856.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

По команде выдается тот самый дамп потока. Поскольку это не java-утилита, а С, нам не нужно тратить время на запуск Java. Утилитка очень короткая — буквально 100 строчек для Windows и для Linux. Доступно на GitHub.

Через этот механизм работает не только утилита jstack, но и утилиты jmap, jinfo и jcmd (по сути один мой jattach исполняет роль всех этих утилит).

На Linux через системный вызов PTRACE_ATTACH (на Windows есть аналогичный) полностью останавливает процесс, к которому подключаемся, замораживая его состояние. Дальше через дебажный API, который позволяет читать память с чужого процесса, утилита jstack вытаскивает все, что нужно, из удаленного JVM процесса. Далее у себя реконструирует структуры JVM и пробегает по ним, сама восстанавливает стек.

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

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Для чего это нужно? Например, в ситуации, когда сервер начинает по какой-то причине тормозить и перестает справляться с потоком входящих запросов. Когда приложение детектит эту ситуацию (например, исчерпался thread pool), запускается дамп потоков, чтобы разработчик в логах мог увидеть, что же система делала в этот момент, что же именно затупило.

Мы у себя в проекте ранее использовали Java API для получения стека потоков, это было очень медленно и занимало кучу памяти. Вместо этого мы теперь собираем информацию через Dynamic Attach — есть к нему Java API, через который как раз и работает утилита jstack. Мы узнаем pid своего же процесса, подключаемся сами к себе через Dynamic Attach и заставляем виртуальную машину саму сгенерировать нам дамп.

Хип-дампы

Утилита jmap в принципе устроена так же.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

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

У jmap также существует 2 режима работы: через Dynamic Attach и через Serviceability Agent (с теми же плюсами и минусами).

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

К счастью, есть хитрый способ, как быстро снимать дампы с мертвых или зависших процессов в forced-режиме.

Давайте покажу на примере.
У меня запущен tomcat с pid 2362. Попробуем снять jmap в forced-режиме:

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Это происходит долго. Ждем пару минут и прерываем. В то же время, если я вызову gcore, core dump получаем за секунду. Занимает он 227 Мб.
Приложение дальше работает: ваши пользователи даже не заметили, что tomcat на секунду перестал принимать подключения.

Дальше jmap можно натравить на этот core-файл.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

В тех случаях, когда что-то пошло плохо, хочется генерировать хип-дамп автоматически. Для этого есть опция виртуальной машины:

-XX:+HeapDumpOnOutOfMemoryError

Она полезна для самого распространенного случая — когда у вас произошло out of memory. Сборки GC можно не дождаться, лучше сразу сдампить хип для последующего анализа и рестартануть приложение.

Также можно дампить хип до и после полной сборки мусора:

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

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

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Интересно, что все перечисленные опции являются manageable, т.е. включать и выключать их можно прямо в рантайме, либо снаружи через команду jinfo, либо из приложения через JMX-интерфейс.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

В Java 8 update 92 появились еще 2 новых опции для автоматизации хип-дампов (как раз чтобы downtime был как можно меньше):

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Честно говоря, опции, конечно, полезные, но можно и без них было обходиться. Ничто не мешало задать одновременно такие 2 опции (сдампить хип на out of memory и потом прибить это же приложение):

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Какие есть способы сгенерировать дамп хипа?

Это можно сделать из java, из native, изнутри процесса, снаружи процесса.
Изнутри процесса проще всего через соответствующий MXBean:

Аналогично если у вас снаружи торчит JMX remote interface, можете через него подключиться и на удаленной виртуальной машине сфорсировать дамп хипа.
Важный момент: jmap работает всегда только на локальной машине, поэтому если у вас нет возможности по ssh к продакшн-серверу подключиться, но необходимо дампить хип, единственный способ его получить — через JMX remote interface.

Быстрее и более гибко из приложения позволяет это сделать все тот же JVMTI. Есть такая замечательная функция IterateOverInstancesOfClass.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Этой функции можно сразу сказать, что нужно обойти только экземпляры какого-то конкретного класса или интерфейса. Например, вы хотите найти объекты только нужного вам типа, а хип у вас на 16 Гб.

Интересный момент, что пользоваться этой функцией нужно в два этапа. Сначала сама эта функция ничего не возвращает, но дает возможность пометить объекты, которые вы хотите потом получить. А уже затем вызовом GetObjectsWithTags можно получить отмеченные объекты в массив jobject.

Моя любимая тема — это serviceability agent — API, который есть в HotSpot. Он изначально создавался для разработчиков JDK и JVM, но нашел применение и у простых Java-программистов.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

В библиотеках Java есть файлик sa-jdi.jar — это как раз API serviceability agent. Он знает все о внутренностях виртуальной машины: какие есть внутренние структуры JVM, по каким оффсетам что лежит, и есть Java API, чтобы этим всем пользоваться. В частности, можно подключиться к другому процессу VM и обойти хип другого процесса.

Давайте рассмотрим на примере.
Представьте, что вы — хакер, получили на короткое время доступ к серверу. Вы хотите получить оттуда какую-то информацию, например, приватные ключи. Но если вы будете дампить хип целиком, это очень быстро заметят, т.к. тут же сработает монитор простоя приложения. А с помощью serviceability agent можно обойти в хипе только объекты нужных классов и распечатать их.
API очень простой.

Уже заготовлен весь фреймворк (в виде класса Tool), и утилита должна просто заэкстендить этот класс и вызвать его метод execute с аргументами (даже обработка аргументов уже происходит за вас). Остается только в методе run реализовать логику.

Это все работает через механизм serviceability agent, когда отлаживаемый процесс полностью останавливается и методом чтения удаленной памяти происходит общение утилиты с Java-процессом. По окончании работы утилиты работа процесса возобновляется.
Попробуем посмотреть наш tomcat таким образом.

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

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Я, конечно, немного схитрил. Print выводит плоское описание объекта, а сам ключик внутри этого байтового массива.

дамп это что в программировании. Смотреть фото дамп это что в программировании. Смотреть картинку дамп это что в программировании. Картинка про дамп это что в программировании. Фото дамп это что в программировании

Поэтому нужно еще дополнительно обойти это поле. У меня на этот случай заготовлен класс FieldPrinter, который движется по объекту и, если его имя совпадает с указанным fieldName, преобразует его в байтовый массив и распечатывает.

На выходе имеем в чистом виде private key с сервера.

У serviceability agent еще много всяких возможностей, которые получить любым другим API не получится. Например, такой экзотический случай: вам нужно обойти не все объекты, а только те, что в oldGen. Поскольку serviceability agent все знает о внутренних структурах, у него есть даже такой API. Можно получить представление хипа в удаленной Java-машине и у него получить представление именно oldGen, опять же этим итератором пройтись по всем объектам и посмотреть, если этот объект бежит только в oldGen, только в этом случае его распечатать.
В данном случае я распечатаю все строки tomcat, которые лежат в oldGen:

Лично встретиться с Андреем в Москве можно будет уже совсем скоро — 7-8 апреля на JPoint 2017. В этот раз он выступит с докладом «JVM-профайлер с чувством такта», в котором расскажет, как можно получить честные замеры производительности приложения, комбинируя несколько подходов к профилированию. Доклад будет «всего» часовой, зато в дискуссионной зоне никто не будет ограничивать вас от вопросов и горячих споров!

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

Источник

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

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