Приложение тормозит. Где узкое место? Почему растёт память? Есть ли дедлок?
(Спойлер: обычно всё сразу, и обычно в пятницу после 17:00.)
Каждый Java-разработчик хотя бы раз сталкивался с необходимостью "заглянуть внутрь" работающей JVM. И каждый раз это требует:
знания утилит jcmd, jfr, jps;
ручного парсинга вывода;
переключения между терминалом, IDE и логами;
а главное — контекста, который сложно передать другому человеку (или ИИ).
Особенно, если этот контекст держится на трёх чашках эспрессо и смутном воспоминании, что «где-то тут я менял пул потоков».
Что если бы ваш AI-ассистент мог сам запустить профилирование, проанализировать JFR-запись и сказать: "Вот метод, который аллоцирует 80% памяти, и вот стек вызовов"?
Я написал JavaPerf — MCP-сервер, который даёт ИИ-инструментам прямой доступ к нативным утилитам JDK для профилирования. Без графических интерфейсов, без ручного CLI — только диалог с ассистентом.
Что такое MCP и зачем это нам?
Model Context Protocol (MCP) — открытый стандарт от Anthropic, который позволяет подключать внешние инструменты к LLM-приложениям через единый интерфейс.
Проще говоря: MCP-сервер — это "мост" между вашим кодом/инфраструктурой и ИИ. Хост (например, Claude Desktop) отправляет запросы, сервер выполняет действия и возвращает структурированный результат.
Что мне нужно было от MCP для Java-профилирования:
Удобство: хранить контекст и jfr логи до/после, чтобы ИИ помнил историю вопросов и результатов профилирования.
Безопасность: только локальный запуск, закрытый контур и все такое, а так же контроль, какие команды может выполнять сервер.
Универсальность: один сервер работает в разных MCP-совместимых клиентах.
Знакомьтесь: JavaPerf
JavaPerf — это MCP-сервер на Node.js, которы�� оборачивает утилиты JDK (jcmd, jfr, jps) в набор инструментов, понятных ИИ-ассистенту.
git: https://github.com/theSharque/mcp-jperf
npm: https://www.npmjs.com/package/javaperf
Что умеет из коробки:
list_java_processes — найти нужный Java-процесс по PID или имени класса
start_profiling / stop_profiling — запустить и остановить JFR-запись с настройками settings=profile
parse_jfr_summary — получить сводку: топ методов, события GC, аномалии
profile_memory / profile_time / profile_frequency — три взгляда на данные: аллокации, CPU, частота вызовов
trace_method — построить дерево вызовов конкретного метода из .jfr
check_deadlock — возвращает JSON с потоками и блокировками. Если в ответе есть цикл — поздравляем, вы нашли тот самый дедлок, который «не может случиться по дизайну».
analyze_threads — диагностика блокировок и потоков
heap_histogram / heap_dump / heap_info — работа с кучей: от гистограммы до full .hprof-дампа — тот самый файл, который «всего 2 ГБ», но почему-то не помещается ни на один диск в нужный момент.
vm_info — быстрая справка по версии JVM, флагам, uptime
Все инструменты возвращают структурированный JSON, который ИИ легко интерпретирует и использует для дальнейших рассуждений.
Как установить и примеры конфигурации есть в гитхабе, нет смысла копипастить одно и тоже.
Сценарий из жизни: как это работает на практике
Представим, что ваше Spring-приложение начало потреблять больше памяти. Вот как может выглядеть диалог с ИИ-ассистентом, подключённым к JavaPerf:
Вы: Приложение myapp начинает тормозить через 2 часа работы. Давай найдём утечку памяти.
AI: Вижу процесс myapp (PID 31415). Запускаю 60-секундную JFR-запись...
выполняет start_profiling с pid=31415, duration=60...прошла минута...
AI: Запись завершена. Анализирую аллокации...
вызывает profile_memory с топ-10 аллокаторовРезультат:
78% аллокаций создаются в com.example.service.DataProcessor.process()
Внутри метода: new byte[1024*1024] в цикле без батчинга
Рекомендация: использовать пул буферов или увеличить размер пакетаВы: Покажи стек вызовов этого метода.
AI: вызывает trace_method с className=com.example.service.DataProcessor, methodName=process
Вот дерево вызовов: Controller.handleRequest() -> Service.processBatch() -> DataProcessor.process() <- горячая точка
Всё это — без переключения на терминал, без ручного парсинга "jfr print". ИИ получает структурированные данные и строит гипотезы в контексте вашего диалога. Самый большой плюс ИИ в том, что он знает как и что искать, а еще он не устает от монотонной работы. Вы просто даете ему задачу и смотрите как он тратит ваши деньги выполняет ее, выдавая вам результат!
Технические детали: как устроен сервер
Архитектура:

Сервер реализует спецификацию MCP через библиотеку @modelcontextprotocol/sdk.
Каждый инструмент — это асинхронная функция, которая:
Валидирует входные параметры (PID, длительность, пути).
Вызывает соответствующую JDK-утилиту через child_process.
Парсит вывод в структурированный JSON.
Возвращает результат + человекочитаемое описание.
Обработка JFR
JFR-записи — это бинарный формат. Вместо ручного разбора мы:
Используем "jfr print --events" для извлечения ключевых событий.
Агрегируем данные по методам, потокам, аллокациям.
Выделяем аномалии: методы с высокой частотой вызовов, длительные блокировки, всплески GC.
Важно: из-за семплинга (~10 мс) очень быстрые методы могут не попасть в ExecutionSample.Если ваш метод выполняется быстрее 10 мс — возможно, он просто слишком хорош для этого мира. Или просто слишком быстрый, чтобы его заметили. В любом случае, для таких случаев есть
trace_method.
Ограничения и как их обойти
Локальность: сервер работает только на машине, где запущен.
Для удалённых серверов используйте SSH-туннель или разверните MCP-хост рядом с приложением.Права доступа: пользователь, запустивший MCP, должен иметь доступ к целевой JVM.
Запускайте от того же пользователя, что и приложение, или настройте jcmd-permissions.Производительность: heap_histogram с флагом all вызывает full GC.
Используйте с осторожностью на продакшене; для мониторинга лучше heap_info.JFR-настройки: по умолчанию используется settings=profile (баланс детализации/оверхеда).
Для продакшена можно передать кастомный .jfc-файл (планируется в будущих версиях).
Заключение
JavaPerf — это не замена YourKit или JVisualVM. Это интерфейс для диалога между разработчиком и системой профилирования, где ИИ выступает как «умный посредник», который знает, какие команды выполнить, как интерпретировать результат и что спросить дальше.
Если вы:
устали переключаться между терминалом и IDE при отладке производительности;
хотите, чтобы ваш AI-ассистент понимал контекст вашего Java-приложения;
верите, что будущее за инструментацией через естественный язык;
— попробуйте JavaPerf. Установка занимает 2 минуты, а первый профилировочный сценарий можно запустить прямо в диалоге с ИИ.
