Команда 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)
TimurZhoraev
01.08.2025 16:27Профайлинг по времени должен быть более тонким, например, для стека вызовов/данных особенно для рекурсивных функций, она может съедать такты, плюс в некоторых случаях если есть цепочка длинных особенно множественных наследований. Указатель на указатель итд перед вызовом короткой функции в этом варианте обычное дело и может съесть довольно много за счёт не последовательного доступа в память. Хотя это тёмная сторона всех дебаггеров - учёт времени не только тела функции но и подготовки аргументов, восстановления регистров/стека, возврата, а если это всё ещё сдобрено вложенными прерываниями.
lsillarionov
Выглядит как очень удобная штука. Может забрать на себя часть задач, решаемых при помощи async-profiler