Отладка JVM через MXBeans на коленке

от автора

Бывает надо заглянуть внутрь JVM.
Увидеть CPU, ядра, потоки, а чаще heapMemory — но у тебя ничего для этого нет.
Ни Prometheus, ни других систем мониторинга. Ещё не настроено окружение.

Backender без мониторинга

Backender без мониторинга

Как можно проверить JVM на коленке?

Есть относительно простой способ сделать это в любых условиях.
На localhost.
На стенде разработки.
На продуктовом стенде (но тут на свой страх и риск — обязательно закрывайте авторизацией).

И здесь мне однажды помог…Custom endpoint, который отдаёт снимок состояния Java Platform MXBeans.


MXBeans

Если начать читать про MXBeans — вы скорее всего начитаете, что это какое-то Legacy.
Когда оно было на пике популярности, я вообще ещё не разрабатывал приложения.
Да, всё меняется. Это и правда устарело, в эпоху систем мониторинга.

Но, в нашем кейсе мониторинга нет. И настраивать затратно. Поэтому продолжаем.

Platform MXBeans (Managed Beans) — это встроенные в Java виртуальную машину стандартные интерфейсы (JMX-компоненты) для управления и мониторинга работы JVM и операционной системы.

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

  • MemoryMXBean — мониторит состояние Heap и Non-Heap памяти, считает загрузку памяти.

  • OperatingSystemMXBean — позволяет заглянуть за пределы JVM и узнать загрузку процессора хоста (CPU), количество ядер и свободную физическую память сервера.

  • ThreadMXBean — считает количество живых потоков (threads), пиковое значение потоков, а также умеет находить взаимные блокировки (Deadlocks).

  • GarbageCollectorMXBean — отдаёт статистику по сборщикам мусора: сколько раз запускались и сколько миллисекунд заняли паузы (Stop-the-world).


Связь с VisualVM, Prometheus

Почти каждый слышал про VisualVM — древний, но крутой софт для просмотра состояния JVM.

Любопытный факт №1
Когда ты подключаешь VisualVM к Java процессу — он сразу же строит графики.
Информацию с Java процесса он собирает как раз благодаря заранее настроенным MXBeans.


Если связать всё вместе

По сути — ты можешь увидеть то что видел в VisualVM — но без VisualVM.
Для этого надо ручками написать Endpoint.
Endpoint опрашивает MXBeans и отправляет статус приложения в ответе.
Ничего сверхъестественного, но думаю это стоит упомянуть, потому что:

  1. Для этого не нужны сторонние библиотеки.

  2. Не нужно специфичное окружение — независимо от среды это запустится

Вот пример Endpoint-а, который собирает полезную информацию о JVM

import org.springframework.web.bind.annotation.GetMappingimport org.springframework.web.bind.annotation.RequestMappingimport org.springframework.web.bind.annotation.RestControllerimport java.lang.management.ManagementFactory@RestController@RequestMapping("/internal/diagnostics")class JvmDiagnosticsController {    @GetMapping("/snapshot")    fun getJvmSnapshot(): Map<String, Any> {        val memory = ManagementFactory.getMemoryMXBean()        val threads = ManagementFactory.getThreadMXBean()        val os = ManagementFactory.getOperatingSystemMXBean()        return mapOf(            "timestamp" to System.currentTimeMillis(),            "memory" to mapOf(                "heap_used_mb" to memory.heapMemoryUsage.used / 1024 / 1024,                "heap_max_mb" to memory.heapMemoryUsage.max / 1024 / 1024,                "non_heap_used_mb" to memory.nonHeapMemoryUsage.used / 1024 / 1024            ),            "threads" to mapOf(                "live" to threads.threadCount,                "peak" to threads.peakThreadCount,                "deadlocked_count" to (threads.findDeadlockedThreads()?.size ?: 0)            ),            "system" to mapOf(                "cpu_load_pct" to (os.systemLoadAverage * 100).toInt(),                "available_processors" to os.availableProcessors            )        )    }}

Любопытный факт №2
Есть способ экспорта этих же метрик MXBean из Java-приложения в формат Prometheus. Стандартом для этого является использование утилиты Prometheus JMX Exporter

P.S.

Не надо использовать способ с Endpoint-ом как основу.
Лучше используйте что-то современное.
Prometheus, Micrometer, Spring Actuator.
Но если ничего нет — есть вот такая палочка-выручалочка.

ссылка на оригинал статьи https://habr.com/ru/articles/1047660/