Апгрейд Java 8 до 21 на 17 000 строк теперь стоит 2,52 доллара машинного времени
Тот самый сервис на Java 8 и Spring Boot 2, который в планировании всегда проигрывает фичам: смета в человеко-неделях не проходит. AWS Transform считает по-другому, 0,035 доллара за минуту работы агента, и апгрейд на 17 000 строк укладывается в 72 минуты.
Перед агентом стоит прогнать детерминированный проход. OpenRewrite разбирает код в дерево с типами, поэтому отличает ваш класс Result от Result из зависимости, чего регулярка не умеет: больше 2800 рецептов, Apache 2.0. Прогон UpgradeToJava21 на Maven-проекте с Java 8 занял 87 секунд вхолодную и 18 на прогретом кеше, а правки легли только в build config, ни строки исходников.
Рецепты бесплатно закрывают предсказуемое, агент добирает хвост, который правилом никто не описал, и его дифф придётся читать глазами. Остальной стек модернизации лежит на dev.to.
Тот самый сервис на Java 8 и Spring Boot 2, который в планировании всегда проигрывает фичам: смета в человеко-неделях не проходит. AWS Transform считает по-другому, 0,035 доллара за минуту работы агента, и апгрейд на 17 000 строк укладывается в 72 минуты.
Перед агентом стоит прогнать детерминированный проход. OpenRewrite разбирает код в дерево с типами, поэтому отличает ваш класс Result от Result из зависимости, чего регулярка не умеет: больше 2800 рецептов, Apache 2.0. Прогон UpgradeToJava21 на Maven-проекте с Java 8 занял 87 секунд вхолодную и 18 на прогретом кеше, а правки легли только в build config, ни строки исходников.
Рецепты бесплатно закрывают предсказуемое, агент добирает хвост, который правилом никто не описал, и его дифф придётся читать глазами. Остальной стек модернизации лежит на dev.to.
👍3❤2
JDK 28 покажет в JFR, договорились ли ваши TLS-соединения на постквантовый обмен ключами
Событие jdk.TLSHandshake в JDK Flight Recorder писало версию протокола и шифронабор, но не то, как стороны вырабатывали общий секрет. В JDK 28 у него появилось поле namedGroup с параметрами обмена ключами: в выводе jfr print там видно, например, X25519MLKEM768, гибрид классической кривой X25519 и постквантового ML-KEM.
По записи с прода теперь видно, какие соединения уже ушли на постквантовую схему, а какие остались на обычной кривой. Для инвентаризации перед миграцией это дешевле отладочного лога TLS, который на нагруженном сервисе обычно не включают.
Событие выключено по умолчанию и в default.jfc, и в profile.jfc, включать явно:
java -XX:StartFlightRecording:settings=default,duration=60s,+jdk.TLSHandshake#enabled=true
Полный пример вывода события показывают в заметке Inside.java.
Событие jdk.TLSHandshake в JDK Flight Recorder писало версию протокола и шифронабор, но не то, как стороны вырабатывали общий секрет. В JDK 28 у него появилось поле namedGroup с параметрами обмена ключами: в выводе jfr print там видно, например, X25519MLKEM768, гибрид классической кривой X25519 и постквантового ML-KEM.
По записи с прода теперь видно, какие соединения уже ушли на постквантовую схему, а какие остались на обычной кривой. Для инвентаризации перед миграцией это дешевле отладочного лога TLS, который на нагруженном сервисе обычно не включают.
Событие выключено по умолчанию и в default.jfc, и в profile.jfc, включать явно:
java -XX:StartFlightRecording:settings=default,duration=60s,+jdk.TLSHandshake#enabled=true
Полный пример вывода события показывают в заметке Inside.java.
Синтаксис, который восемь лет лежит в драфте JEP, предлагают включать препроцессором перед javac
Декоратор или адаптер наполовину состоит из методов, которые только зовут то же самое у обёрнутого объекта. В самой JDK у
JEP 8209434 «Concise Method Bodies» Брайана Гётца предлагает записывать их как лямбды:
Автор статьи ждать перестал и собрал препроцессор java-composition: он разворачивает такие тела в обычный Java-код до того, как файл дойдёт до javac, начиная с Java 8.
Цена — исходник, который без препроцессора не соберётся ни у кого. Взяли бы такое в проект, который поддерживать ещё пять лет?
Декоратор или адаптер наполовину состоит из методов, которые только зовут то же самое у обёрнутого объекта. В самой JDK у
Collections.UnmodifiableCollection таких методов 14.JEP 8209434 «Concise Method Bodies» Брайана Гётца предлагает записывать их как лямбды:
public int size() -> c.size(); или ссылкой на метод: public int size() = aList::size;. Заявку подали в августе 2018 года, и она до сих пор в статусе Draft: ни целевого релиза, ни preview-флага. В C# такие тела работают с 2015 года.Автор статьи ждать перестал и собрал препроцессор java-composition: он разворачивает такие тела в обычный Java-код до того, как файл дойдёт до javac, начиная с Java 8.
Цена — исходник, который без препроцессора не соберётся ни у кого. Взяли бы такое в проект, который поддерживать ещё пять лет?
🤣1
Девять convention-плагинов Gradle в проде JetBrains заменили декларативным конфигом сборки
Логика сборки крупного JVM-проекта обычно живёт в buildSrc: convention-плагины на Kotlin, которые сами надо компилировать и чинить при каждом апгрейде Gradle. JetBrains перевела на Kotlin Toolchain бэкенд klibs.io: прод на JDK 21, Spring Boot 4 со Spring AI, PostgreSQL и OpenSearch. Девять плагинов свернулись в шаблоны Toolchain, а Jib и Git Properties, у которых встроенного аналога нет, переписали как локальные плагины.
Отдельно про Maven Central: Sonatype скоро включит квоты на число файлов в публикации. В 0.12 из неё убрали контрольные суммы файлов подписи (.asc.sha1) — они не нужны, а место в квоте занимают.
Toolchain пока в версии 0.x, публикация библиотек в статусе preview, для фич 0.12 нужна IntelliJ IDEA 2026.2.1. Переносить рабочую сборку рано, а в список на перепроверку положить стоит.
Логика сборки крупного JVM-проекта обычно живёт в buildSrc: convention-плагины на Kotlin, которые сами надо компилировать и чинить при каждом апгрейде Gradle. JetBrains перевела на Kotlin Toolchain бэкенд klibs.io: прод на JDK 21, Spring Boot 4 со Spring AI, PostgreSQL и OpenSearch. Девять плагинов свернулись в шаблоны Toolchain, а Jib и Git Properties, у которых встроенного аналога нет, переписали как локальные плагины.
Отдельно про Maven Central: Sonatype скоро включит квоты на число файлов в публикации. В 0.12 из неё убрали контрольные суммы файлов подписи (.asc.sha1) — они не нужны, а место в квоте занимают.
Toolchain пока в версии 0.x, публикация библиотек в статусе preview, для фич 0.12 нужна IntelliJ IDEA 2026.2.1. Переносить рабочую сборку рано, а в список на перепроверку положить стоит.
Промпт прошёл все офлайн-проверки и всё равно уронил P95 на 38%, но канареечный выкат ловит это за минуты
Правку промпта не отсекает ни один привычный гейт: компилятор её не видит, юнит-тесты зелёные, офлайн-набор из 40 кейсов тоже. А на живом трафике переформулированное описание инструмента научило агента вызывать его дважды за ход: вызовов на диалог стало 5,4 вместо 3,1, P95 вырос на 38%. Тестовые транскрипты короткие по замыслу, реальные диалоги длинные, и каждый лишний вызов удваивает ожидание.
В десятой части серии про агента на Spring Boot собрана рантайм-обвязка: раздача процента трафика на новую версию, автоматический переход на запасную модель при деградации основной и потолок расходов на модель.
Если промпты у вас едут в прод вместе с кодом, начинать стоит с процента трафика, который возвращается в ноль одной настройкой, и графика вызовов инструментов на диалог.
Правку промпта не отсекает ни один привычный гейт: компилятор её не видит, юнит-тесты зелёные, офлайн-набор из 40 кейсов тоже. А на живом трафике переформулированное описание инструмента научило агента вызывать его дважды за ход: вызовов на диалог стало 5,4 вместо 3,1, P95 вырос на 38%. Тестовые транскрипты короткие по замыслу, реальные диалоги длинные, и каждый лишний вызов удваивает ожидание.
В десятой части серии про агента на Spring Boot собрана рантайм-обвязка: раздача процента трафика на новую версию, автоматический переход на запасную модель при деградации основной и потолок расходов на модель.
Если промпты у вас едут в прод вместе с кодом, начинать стоит с процента трафика, который возвращается в ноль одной настройкой, и графика вызовов инструментов на диалог.
👎1
Общий обработчик исключений убирает try/catch из контроллеров, но свалка переезжает в него самого
В контроллере на каждый эндпоинт по два catch: свой UserAlreadyExistsException в 409, остальное в 500 со строкой «Internal server error». В соседнем контроллере то же самое, но статус и текст уже другие. Всё это уносится в @RestControllerAdvice, и метод снова возвращает только успешный ответ.
Спор начинается дальше. В статье на dev.to автор разводит бизнес-ошибки и системные. Вторые обычно закрывают одним обработчиком на Exception.class, и он же превращает в аккуратный 500 то, что должно было упасть громко и попасть в алерты.
А со Spring Boot 3 в фреймворке уже есть ProblemDetail: стандартное тело ошибки по RFC. Свой ErrorResponse при этом всё равно пишут почти все.
Как разложены исключения у вас?
В контроллере на каждый эндпоинт по два catch: свой UserAlreadyExistsException в 409, остальное в 500 со строкой «Internal server error». В соседнем контроллере то же самое, но статус и текст уже другие. Всё это уносится в @RestControllerAdvice, и метод снова возвращает только успешный ответ.
Спор начинается дальше. В статье на dev.to автор разводит бизнес-ошибки и системные. Вторые обычно закрывают одним обработчиком на Exception.class, и он же превращает в аккуратный 500 то, что должно было упасть громко и попасть в алерты.
А со Spring Boot 3 в фреймворке уже есть ProblemDetail: стандартное тело ошибки по RFC. Свой ErrorResponse при этом всё равно пишут почти все.
Как разложены исключения у вас?
Совет не оптимизировать руками и довериться JIT держался на цене специалиста, а она рухнула
В любом Spring Boot сервисе есть эндпоинты, которые тормозят годами: снять профиль, найти горячий метод, проверить гипотезу, откатить. Несколько дней инженера ради неочевидного выигрыша.
Дэн Лу в эссе «There's no reason for software to be slow anymore» пишет, что человеко-время на такую итерацию упало в тысячи раз: запуск агента на его собственном сценарии с ripgrep занял около двух минут. Джейми Брэндон отдал агенту недоделанное тестовое Anthropic по производительности и получил результат лучше своего.
Java стоит на обратном: пиши предсказуемый код, JIT разберётся. Это верно, пока проверка гипотезы дороже выигрыша. Теперь она стоит минуты, зато поддерживать неочевидные правки в горячем пути всё равно людям. Рабочий процесс для Spring Boot. Пустили бы агента в горячий путь своего сервиса?
В любом Spring Boot сервисе есть эндпоинты, которые тормозят годами: снять профиль, найти горячий метод, проверить гипотезу, откатить. Несколько дней инженера ради неочевидного выигрыша.
Дэн Лу в эссе «There's no reason for software to be slow anymore» пишет, что человеко-время на такую итерацию упало в тысячи раз: запуск агента на его собственном сценарии с ripgrep занял около двух минут. Джейми Брэндон отдал агенту недоделанное тестовое Anthropic по производительности и получил результат лучше своего.
Java стоит на обратном: пиши предсказуемый код, JIT разберётся. Это верно, пока проверка гипотезы дороже выигрыша. Теперь она стоит минуты, зато поддерживать неочевидные правки в горячем пути всё равно людям. Рабочий процесс для Spring Boot. Пустили бы агента в горячий путь своего сервиса?