1. JMX (Java Management Extensions): сердце мониторинга JVM
Мониторинг — это как регулярный медосмотр для вашего приложения. Если логирование можно сравнить с дневником, куда записывается всё, что уже случилось, то мониторинг — это набор приборов, показывающих состояние системы прямо сейчас: температуру, пульс, давление, уровень сахара и другие жизненно важные показатели JVM.
Он помогает понять, сколько памяти реально используется и не течёт ли она, сколько потоков работает и в каком они состоянии — ждут, выполняются или заблокированы. Можно увидеть, как часто срабатывает сборщик мусора, насколько загружен процессор и вовремя заметить тревожные симптомы вроде внезапного роста памяти или числа потоков.
Если коротко, логирование рассказывает, что уже произошло, а мониторинг показывает, что происходит прямо сейчас.
Основы JMX: что это и зачем
JMX — это технология в Java, которая позволяет наблюдать за жизнью вашего приложения изнутри и даже немного управлять ею. Она работает через специальные объекты — MBean (Management Bean). Можно сказать, это как «датчики» и «тумблеры» внутри JVM: одни показывают состояние системы, другие позволяют что-то подкрутить.
С помощью JMX вы можете узнать, сколько памяти сейчас выделено JVM, сколько потоков активно, сколько времени уходит на сборку мусора и многое другое — без необходимости лезть в код или перезапускать приложение.
Как это устроено
В JVM «из коробки» уже есть множество MBean-ов, которые дают информацию о:
- памяти (heap, non-heap);
- сборщиках мусора (GC);
- потоках;
- классах (сколько загружено, выгружено);
- и даже о самой JVM (версия, параметры запуска).
JMX — это как панель приборов в машине. Вы видите скорость, обороты, температуру двигателя — и всё это доступно через стандартные датчики (MBean-ы).
Как получить доступ к JMX
Самый простой способ — использовать стандартную утилиту JConsole, которая входит в JDK.
Запуск JConsole
- Откройте терминал/командную строку.
- Выполните команду:
jconsole - Выберите процесс Java, который хотите мониторить (например, ваше приложение).
JConsole подключится к JVM через JMX и покажет графики и таблички: использование памяти, количество потоков, активность сборщика мусора и т. д.
Пример: посмотреть память и потоки
В JConsole откройте вкладки "Memory" и "Threads". Вы увидите, как меняется объём используемой памяти, сколько потоков сейчас живёт, какие из них активны и какие ждут.
Кастомные MBean-ы
Можно создавать свои MBean-ы для мониторинга собственных метрик (например, количества обработанных заказов). Но это уже тема для продвинутых: стандартные MBean-ы дают очень много информации.
2. VisualVM — визуальный мониторинг и профилирование
Если JConsole — это «приборная панель», то VisualVM — это целый диагностический центр с рентгеном, МРТ и анализом крови. Он позволяет не только мониторить, но и профилировать приложение, снимать heap dump, анализировать утечки и видеть, какие методы занимают больше всего времени.
Установка и запуск VisualVM
- VisualVM входит в поставку JDK (обычно как jvisualvm), но свежую версию можно скачать на visualvm.github.io.
- Запускается командой:
jvisualvm - После запуска вы увидите список всех Java-процессов, запущенных на вашей машине.
Подключение к процессу
- Найдите свой процесс (например, Main или MyApp) в списке.
- Дважды кликните по нему — откроется вкладка с информацией о процессе.
- Готово! Теперь вы видите:
- Использование CPU и памяти в реальном времени.
- Количество потоков и их состояние.
- Список загруженных классов.
- Возможность снять heap dump и thread dump.
Основные возможности VisualVM
С VisualVM можно наблюдать, как используется память — и heap, и non-heap. На графике видно, растёт ли потребление или стабилизируется. Чтобы проверить работу сборщика мусора, нажмите кнопку "Perform GC" — JVM сразу попытается очистить память. Можно сделать heap dump (снимок памяти) и изучить его для поиска утечек.
Инструмент покажет и состояние потоков: сколько их запущено, какие работают, ждут или заблокированы. Если случился deadlock, VisualVM поможет его обнаружить и показать взаимоблокировки.
Для глубокого анализа есть профилирование: вы увидите «горячие» методы, которые «едят» больше всего процессорного времени или памяти. Это полезно при диагностике неожиданного падения производительности.
Пример: мониторим мини-приложение
public class MemoryLeakDemo {
public static void main(String[] args) throws InterruptedException {
List<byte[]> memoryConsumers = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
memoryConsumers.add(new byte[1024 * 1024]); // 1 MB
Thread.sleep(100); // Немного подождём, чтобы график был плавнее
}
System.out.println("Готово! Не забудьте посмотреть в VisualVM :)");
Thread.sleep(60000); // Держим приложение открытым для анализа
}
}
Теперь:
- Запустите программу.
- Откройте VisualVM, подключитесь к процессу.
- Посмотрите, как растёт использование памяти.
- Снимите heap dump, найдите массивы, занимающие память.
3. Java Flight Recorder (JFR): чёрный ящик для JVM
Что такое JFR
Java Flight Recorder — встроенный в JVM инструмент для сбора подробных событий о работе приложения. Это «чёрный ящик»: JFR пишет, что происходит в JVM, чтобы потом найти узкие места или причины инцидента.
JFR собирает:
- события GC;
- информацию о потоках;
- частоту вызова методов и профили времени;
- паузы и задержки;
- исключения и ошибки.
Как включить JFR
С Java 11+ JFR есть прямо в OpenJDK.
Запуск с JFR
java -XX:StartFlightRecording=filename=recording.jfr,duration=60s,settings=profile -jar MyApp.jar
- filename=recording.jfr — куда сохранить запись.
- duration=60s — сколько писать.
- settings=profile — уровень детализации (default, profile, continuous).
Просмотр результатов
Для анализа файла .jfr используется JDK Mission Control (JMC):
- Скачать JMC: jdk.java.net/jmc
- Открыть файл recording.jfr.
- Изучить графики, «горячие» методы, паузы GC и активность потоков.
Пример: снимаем «чёрный ящик»
- Запустите приложение с JFR (см. команду выше).
- Откройте JDK Mission Control, загрузите файл записи.
- Оцените «горячие» места по CPU/памяти, частоту сборок мусора и количество активных потоков.
4. Практика: мониторим приложение
import java.util.ArrayList;
import java.util.List;
public class MonitoringExample {
public static void main(String[] args) throws InterruptedException {
List<byte[]> memory = new ArrayList<>();
for (int i = 0; i < 50; i++) {
memory.add(new byte[2 * 1024 * 1024]); // 2 MB
Thread.sleep(500);
}
// Запускаем поток
new Thread(() -> {
while (true) {
try {
Thread.sleep(1000);
System.out.println("Фоновый поток работает...");
} catch (InterruptedException e) {
break;
}
}
}).start();
Thread.sleep(20000); // Держим приложение открытым для мониторинга
}
}
Действия:
- Запустите программу.
- Откройте VisualVM, найдите процесс, посмотрите на график памяти и потоки.
- Попробуйте снять heap dump и thread dump.
- Для продвинутых: запустите с JFR и посмотрите результаты в JMC.
5. Полезные нюансы
Сравнительная таблица инструментов мониторинга
| Инструмент | Для чего подходит | Как запускать | Особенности |
|---|---|---|---|
| JConsole (JMX) | Основные метрики JVM, потоки, GC | |
Просто, входит в JDK |
| VisualVM | Мониторинг, профилирование, heap dump | |
Графики, анализ памяти, CPU |
| Java Flight Recorder | Глубокий анализ событий JVM | |
Анализ в JMC, «чёрный ящик» |
| JDK Mission Control | Просмотр файлов JFR | отдельная программа | Подробная аналитика, отчёты |
Рекомендации
- Мониторьте не только в продакшене, но и на этапе тестирования. Так вы раньше поймаете утечки памяти и «зависшие» потоки.
- Heap dump — не больно! Снимайте дамп памяти при подозрении на утечку и изучайте его в VisualVM.
- Не бойтесь экспериментировать с JFR. Даже если не всё понятно сразу, события и графики помогут найти узкие места.
- JMX можно использовать программно. Например, чтобы отправлять метрики в Prometheus/Grafana.
- Профилирование — не для постоянной работы. Включайте профайлеры точечно, иначе приложение может замедлиться.
6. Типичные ошибки при мониторинге JVM
Ошибка №1: Не мониторить вообще. Многие новички думают, что если приложение «работает», то всё хорошо. На деле проблемы с памятью и потоками часто проявляются под нагрузкой или спустя время. Не ленитесь открывать VisualVM/JConsole хотя бы периодически.
Ошибка №2: Снимать heap dump на огромных приложениях без подготовки. Heap dump большого приложения может весить гигабайты и «заморозить» процесс на несколько секунд. Делайте это в тестовой среде или в «тихие» часы, если речь о продакшене.
Ошибка №3: Игнорировать показатели GC и потоков. Постоянно высокая доля времени на GC — тревожный сигнал! А если число потоков стабильно растёт — ищите утечку потоков.
Ошибка №4: Не анализировать результаты мониторинга. Просто открыть VisualVM — мало. Смотрите, какие объекты занимают память, какие методы «жрут» CPU, почему появляются deadlock-и. Разбирайте стек-трейсы и причины.
Ошибка №5: Использовать профайлеры в продакшене без понимания. Профилирование может значительно замедлить приложение. Включайте его только для диагностики, а не «на постоянку».
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ