Команда Spring АйО провела небольшое исследование JEP 520. В Java 25 JFR (Java Flight Recorder) позволит точно отслеживать выполнение конкретных методов — без изменения исходников, без логирования и без сторонних Java-агентов.

? Зачем это нужно?


Допустим, приложение долго стартует или внезапно теряет соединения с БД. Раньше приходилось:

  • Логировать вручную

  • Добавлять JFR-события в код

  • Подключать агент через -javaagent

  • Пытаться угадать с sampling-профайлером

  • Использовать Spring AOP и @Around-аспекты

Теперь всё можно сделать проще: точно, из коробки и с минимальной настройкой.

⚙️ Что добавили?

Два новых события в JFR:

  • jdk.MethodTiming — считает вызовы, замеряет среднее, мин/макс время выполнения

  • jdk.MethodTrace — пишет стек вызова и длительность каждого вызова

И самое главное: всё настраивается фильтрами, без изменений в коде!

? Пример использования


Допустим, вы хотите посмотреть, как часто и как долго вызывается HashMap::resize.

Запуск:

java -XX:StartFlightRecording=method-trace=java.util.HashMap::resize,filename=resize.jfr ...

Анализ:

jfr print --events jdk.MethodTrace resize.jfr

Пример вывода:

jdk.MethodTrace {
    startTime = 00:39:26.379
    duration = 0.00113 ms
    method = java.util.HashMap.resize()
    eventThread = "main"
    stackTrace = [
      java.util.HashMap.putVal(...)
      java.util.HashMap.put(...)
      ...
      java2d.J2Ddemo.main(String[]) line: 674
    ]
}

Как ещё можно использовать?

Замерить все <clinit> и понять, что тормозит:

-XX:StartFlightRecording:method-timing=::<clinit>,filename=init.jfr

Отслеживать методы с аннотацией @Get из JAX-RS:

jcmd <pid> JFR.start method-timing=@jakarta.ws.rs.GET

Сравнивать, сколько раз и с каким временем выполнялся метод:

<setting name="filter">
  com.example.Foo::doSomething;
  com.example.Bar::handle
</setting>

Какой результат?


После запуска вы получаете .jfr-файл, который можно:

  • Просмотреть через jfr print или jfr view

  • Подгрузить в JDK Mission Control

  • Анализировать удалённо через JMX/RemoteRecordingStream

В чём польза?

  • Быстро находим горячие методы

  • Точно отслеживаем, что вызывает FileDescriptor::close

  • Проверяем гипотезу, стал ли метод быстрее после оптимизации

  • Отлаживаем проблемы без доступа к коду сторонних библиотек

Вывод

Можно будет не модифицировать код, городить прокси или запускать -javaagent. Достаточно задать нужный фильтр, чтобы точно знать, где и когда выполняется нужный метод.


Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано

Комментарии (2)


  1. lsillarionov
    01.08.2025 16:27

    Выглядит как очень удобная штука. Может забрать на себя часть задач, решаемых при помощи async-profiler


  1. TimurZhoraev
    01.08.2025 16:27

    Профайлинг по времени должен быть более тонким, например, для стека вызовов/данных особенно для рекурсивных функций, она может съедать такты, плюс в некоторых случаях если есть цепочка длинных особенно множественных наследований. Указатель на указатель итд перед вызовом короткой функции в этом варианте обычное дело и может съесть довольно много за счёт не последовательного доступа в память. Хотя это тёмная сторона всех дебаггеров - учёт времени не только тела функции но и подготовки аргументов, восстановления регистров/стека, возврата, а если это всё ещё сдобрено вложенными прерываниями.