Задать вопрос
@artemfisher

Почему Java Flight Recorder в Spring Boot не пишет в файл?

Включаю Java Flight Recorder:

@SpringBootApplication
public class AppInitializer {
	
	public static void main(String[] args)
	{		
		var context = new SpringApplicationBuilder(AppInitializer.class)
		.child(WebConfig.class)		
		.initializers(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.DEBUG))		
		.web(WebApplicationType.SERVLET)
		.applicationStartup(new FlightRecorderApplicationStartup())			
		.run(args);			
	}
}


Архивирую в jar и запускаю приложение разными командами:
java -XX:StartFlightRecording:filename=recording.jfr,duration=10s,settings=profile,dumponexit=true -jar DatingSpringBoot.jar --myparam=val

java -XX:StartFlightRecording:filename=recording.jfr,duration=10s,settings=profile -jar DatingSpringBoot.jar --myparam=val


В обоих случаях пишет, что запись началась:
[1.327s][info][jfr,startup] Started recording 1. The result will be written to:
[1.327s][info][jfr,startup]
[1.327s][info][jfr,startup] C:\Users\Артём\git\DatingSpringBoot\DatingSpringBoot\target\recording.jfr
[5.316s][warning][os ] Unable to resolve PDH index: (230)
[5.318s][warning][os ] Please check the registry if this performance object/counter is disabled
[6.617s][warning][os ] Unable to resolve PDH index: (230)
[6.618s][warning][os ] Please check the registry if this performance object/counter is disabled


В итоге файл создается, но он пустой. Даже после принудительного завершения работы приложения (Ctrl + C).
  • Вопрос задан
  • 197 просмотров
Подписаться 1 Простой 2 комментария
Помогут разобраться в теме Все курсы
  • Академия Эдюсон
    Java-разработчик + ИИ
    8 месяцев
    Далее
  • Нетология
    Java-разработчик с нуля
    12 месяцев
    Далее
  • ProductStar × РБК
    Профессия: Java-разработчик + ИИ
    9 месяцев
    Далее
Пригласить эксперта
Ответы на вопрос 2
avleonov97
@avleonov97
Java разработчик
Здравствуйте!

Имею значительный опыт работы с Java Flight Recorder и сталкивался с различными ошибками при его использовании. Хочу отметить, что JFR весьма чувствителен к версиям Java и их поставщикам. В настоящее время существует множество кастомных сборок JDK, которые могут содержать изменения, влияющие на работу профилировщика.

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

Также хочу обратить внимание на параметры запуска. Вы указали duration=10s — это время записи метрик, однако я не уверен, что ваше приложение успевает полностью запуститься за этот промежуток. Вполне вероятно, что JFR не успевает произвести запись из-за недостаточного времени.

Рекомендую начать с минимальной конфигурации и постепенно добавлять параметры:

-XX:StartFlightRecording=settings=default,name=alex


После успешного запуска можно последовательно добавлять другие параметры, сверяясь с официальной документацией:
https://docs.oracle.com/en/java/javase/11/docs/api...

Такой подход поможет точно определить, какой именно параметр вызывает проблему.

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

Буду благодарен, если дадите обратную связь по итогу. Спасибо!
Ответ написан
Комментировать
@Sharque
Программис
Я на такое натыкался. Пара мыслей.

С duration=10s файл дописывается только в конце записи, до этого JFR держит данные во временном репозитории. А он по умолчанию лежит в %TEMP%, у вас это путь с кириллицей (C:\Users\Артём\...). Не уверен, что дело в этом, но я бы сначала вынес всё в ASCII-путь:

java -XX:FlightRecorderOptions:repository=C:\jfr\repo ^
     -XX:StartFlightRecording:filename=C:\jfr\recording.jfr,duration=60s,settings=profile ^
     -jar DatingSpringBoot.jar


Ещё dumponexit срабатывает только при нормальном завершении JVM, а из IDE процесс часто убивается жёстко.

Сам я давно перестал запускать JFR флагами и управляю записью на живом процессе через jcmd (JFR.start, потом JFR.dump), так от завершения ничего не зависит. FlightRecorderApplicationStartup, кстати, для записи в файл не нужен, он только добавляет события старта Spring.

Чтобы не разбирать .jfr руками, я сделал себе MCP-сервер javaperf (https://github.com/theSharque/mcp-jperf). Пишу в Cursor «найди Spring Boot процесс, запиши JFR на минуту и покажи горячие методы и аллокации», и агент сам всё это делает через jcmd.

{ "mcpServers": { "javaperf": { "command": "npx", "args": ["-y", "javaperf"] } } }
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы