Инструменты для мониторинга Java VM и копания внутри

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

Программы

VisualVM — раньше в составе JDK были две утилиты: jconsole и visualvm, теперь jconsole удалена, а с Java 9 visualvm поставляется отдельно. Незаменимый помощник для профилирования кода. Бесплатен. Куча плагинов для профилирования кода и сбора статистики.

Java Mission Control. Раньше утилита шла в составе JDK, теперь выделена в отдельный проект. Старая jmc не понимает дампов новых JVM. Поэтому, если перешли на java12 или java13 надо выкачивать JMC 7. НО! на сайте проекта нет ссылки на скачивание! Вам предлагается скачать исходный код и собрать JMC самостоятельно. Однако нашлись добрые люди и скомпилировали JMC для вас: например, это сделал Алексей Шипилев. На своем сайте в темной каморке он выкладывает свежие билды JMC под MacOS X, Windows и Linux. Спасибо! Про JMC есть подробная презентация от Алексея Рагозина.

jmh — микробенчмаркинг от Алексея Шипилёва (см. презентацию). Была раньше отдельная библиотека, теперь идет в составе JDK.

jmx — Java-интерфейс, через который можно собирать статистику с работающего приложения и управлять его свойствами.

Утилиты JDK

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

Для мониторинга приложения и сбора статистики можно использовать утилиты jps, jinfo, jstack и jmap.

# jps -mlv

Выведет список только Java-процессов на данной машине (в отличие от стандартного Unix/Linux ps). Выведет id процесса, его Main-class и параметры, с которыми процесс был запущен. Main-class и параметры полезны, чтобы отличить один процесс от другого, если у вас запущено несколько вариантов одной и той же программы с разными параметрами.

# jmap -heap <pid>

Выведет дамп памяти вашей Java-программы. Увы, работает только с Java 8, если утилита jmap из Java 8 JDK. Утилита считается экспериментальной и в новых JDK не поддерживается.

# jinfo <pid>

Выведет много-много полезной информации о параметрах JVM, флагах, аргументах запуска программы.

# jstack <pid>

Выведет дамп всех потоков вашей Java-программы.

Стоит помянуть ещё одну полезную утилиту: jcmd. В новейших релизах JDK она заменяет старые утилиты, которые считаются устаревшими (deprecated) и экспериментальными (experimental) и больше не поддерживаются. Предполагается, что вместо зоопарка утилит jps, jinfo, jstack и jmap, достаточно освоить jcmd, которая эффективно заменит их все. Стоит отметить, что информация, которую выдает jcmd может заметно отличаться по полноте и структуре от того, что выдают старые утилиты. В JDK13 эти утилиты еще поставляются, но не гарантируют, что они там останутся в следующих релизах.

Формат команд jcmd простой и прекрасно описан в документации на сайте Oracle, например вот вариант для Java 8 LTS, Java11 LTS, и для свеженькой Java13:

# jcmd <pid процесса> <команда>

Я дам лишь несколько вариантов, которые считаю полезными:

# jcmd <pid> VM.uptime# jcmd <pid> VM.command_line
# jcmd <pid> VM.flags
# jcmd <pid> VM.system_properties
# jcmd <pid> VM.info - замена jinfo
# jcmd <pid> GC.heap_info
# jcmd <pid> Thread.print -l
# jcmd <pid> PerfCounter.print

Список команд (а их очень много), которые поддерживаются утилитой jcmd можно посмотреть так:

# jcmd <pid> help

покажет только список команд, или

# jcmd <pid> help -all

Покажет список команд с объяснениями, что команда делает.

С помощью jcmd можно запускать и останавливать внутренний монитор сбора статистики Java Flight Recorder. Статистику можно записывать в файл, который можно просмотреть другой утилитой — Java Mission Control (о ней было уже сказано выше).

Обратите внимание, что в команде надо указывать pid процесса. Все дело в том, что у вас на машине может работать несколько Java-приложений под разными JVM. Например, у меня одно приложение до сих пор работает под Java 8, а другое — уже под Java 13. И для каждой JVM имеется свой набор команд, который поддерживает jcmd. Поэтому на некоторые команды Java8 может сказать «Not supported».

Сбор статистики как рутина

Важное замечание: При обращении данных утилит к JVM для сбора статистики, JVM должна на короткое время сбора данных остановиться сама и остановить все работающие потоки вашего приложения. Это значит не следует собирать статистику на PROD-е в критические для вашей системы моменты. Как правило я планирую сбор статистики с помощью  утилиты cron на определенные часы, когда рынок закрыт, торги не ведутся и останов JVM на короткое время ничему не критическому не помешает.

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

Java Agents

JVM имеет Java Agents API, который позволяет подключать к JVM сторонние утилиты. Java agents  — это «агенты», написанные на Java. Подключаются к приложению при старте с помощью параметра:

 -javaagent:<path-to-agent-jar>=<options>

JVM TI-агенты — другой способ подключить стороннюю утилиту к JVM при старте. JVMTI-агенты пишутся на C или C++. Они позволяют глубже заглянуть во внутренности JVM, но при этом высок риск грохнуть ее. Подключаются к приложению при старте с помощью параметра:

-agentlib:<agent-lib-name>=<options>

или

-agentpath:<path-to-agent>=<options>

Сторонние утилиты

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

JITWatch — отличная open-source утилита, показывающая стадии компиляции вашего кода JIT-компилятором во время исполнения.

 

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

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Google photo

Для комментария используется ваша учётная запись Google. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s