Чашечка Java
الذهاب إلى القناة على Telegram
Лучшие материалы по Java на русском и английском Разместить рекламу: @tproger_sales_bot Правила общения: https://tprg.ru/rules Другие каналы: @tproger_channels
إظهار المزيد8 313
المشتركون
-424 ساعات
-247 أيام
-6530 أيام
أرشيف المشاركات
8 313
Spring Boot 4 и BoxLang: как сохранить CFML-шаблоны при миграции
BoxLang Spring Boot Starter позволяет оставить представления на CFML, языке шаблонов ColdFusion, пока контроллеры и другие части приложения переносятся на Spring. В Maven-проект добавляется стартер версии 1.0.0, а свойство
boxlang.suffix=.cfm переключает его обработчик представлений с файлов .bxm на .cfm.
Контроллер остаётся обычным для Spring MVC: возвращает логическое имя представления, а атрибуты Model автоматически становятся переменными CFML. В шаблонах продолжают работать cfoutput, условия, циклы и подключение общих блоков.
Это даёт путь для поэтапной миграции без одновременной переписи всех представлений. В готовом примере показаны настройка проекта, передача данных из контроллера и запуск шаблонов на Spring Boot 4.8 313
JDK 25 и G1: почему Arrays.fill замедлился в 265 раз
В JMH-тесте на Apple M4 Max заполнение массивов ссылок заняло у G1 139 мс, а у ParallelGC 0,5 мс. При этом сборка мусора не запускалась: почти всё время ушло в JIT-код
Arrays.fill.
Причина: барьер записи, который JVM добавляет к каждому присваиванию ссылки. Он помечает изменённые участки кучи, чтобы G1 не сканировал всё старое поколение. На результат также повлияли размер регионов G1 и переход массива в старое поколение.
Разбор JMH-бенчмарка и ARM64-инструкций HotSpot объясняет, почему одной инструкции оказалось недостаточно. Замедление относится к этой конфигурации: перед настройкой G1 повторите замер на своей нагрузке.8 313
Как настроить MFA в Spring Security 7 для приложения и отдельных эндпоинтов
Spring Security 7, доступный со Spring Boot 4, добавил
FactorGrantedAuthority. После входа по паролю пользователь получает FACTOR_PASSWORD, а после одноразового токена из письма — FACTOR_OTT. Доступ открывается, когда собраны все обязательные факторы.
Для MFA во всём приложении аннотация @EnableMultiFactorAuthentication связывает фильтры входа и создаёт проверку требуемых факторов. Стандартная форма не умеет задавать их порядок, поэтому для последовательного сценария понадобятся собственные страницы.
Чтобы усилить только /admin/**, аннотации передают пустой список факторов, а отдельный AuthorizationManagerFactory назначают этому маршруту. Остальные запросы сохраняют однофакторную проверку. Конфигурация обоих вариантов приведена с кодом.8 313
Как StructuredTaskScope в JDK 27 отменяет лишнюю работу при сбое
Два независимых вызова к сервисам последовательно занимают около двух секунд. Виртуальные потоки с
Future сокращают успешный запуск примерно до секунды, но при сбое одного вызова через 200 мс второй продолжает работу. Закрытие ExecutorService ждёт его завершения, хотя результат уже не нужен.
StructuredTaskScope объединяет подзадачи: ошибка одной прерывает соседнюю, а join() сообщает о сбое всей группы. В примере метод возвращается примерно через 200 мс вместо полной секунды.
Сравнение трёх реализаций учитывает седьмую предварительную версию API в JDK 27 и проверяемое исключение ExecutionException. Для запуска нужен --enable-preview. Ограничение сохраняется: задача должна реагировать на прерывание, а закрытие области ждёт завершения всех подзадач.8 313
Как подтвердить взаимную блокировку по дампу потоков Java
Если JVM перестала выполнять работу, снимите несколько дампов с интервалом в несколько секунд:
jcmd <pid> Thread.print -l или jstack -l <pid>.
Найдите потоки в состоянии BLOCKED. Сопоставьте монитор после waiting to lock с потоком, который держит его после locked. Если цепочка вернулась к первому потоку, взаимная блокировка подтверждена.
WAITING и TIMED_WAITING сами по себе нормальны. Практический разбор дампов показывает, как сверить стеки с метриками. Исправлять нужно порядок захвата блокировок: увеличение пула цикл не разорвёт.8 313
Spring Boot 4: настраиваем экспорт логов, метрик и трассировок через OpenTelemetry
В Spring Boot 4 появился собственный OpenTelemetry starter. Spring рекомендует его вместо Java-агента и стороннего starter с альфа-зависимостями.
Для логов нужны Logback appender,
logback-spring.xml и вызов install(). В 4.0.0 экспорт без Actuator не работал, обе ошибки исправили в 4.0.1.
Метрики потребуют Micrometer и дополнительных bean-компонентов, для трассировок достаточно адреса экспорта. Полная схема настройки включает Docker Compose с Grafana LGTM. Проверьте адрес логов: нужен /v1/logs, не /v1/traces.8 313
DAGP 3.5.0 проверяет бинарную совместимость дубликатов классов в Gradle
Если два JAR содержат класс с одинаковым полным именем, JVM загрузит первый найденный в пути классов. Поэтому порядок зависимостей может решить, какая реализация попадёт в работу. На этом же поведении строятся атаки Maven-Hijack.
Dependency Analysis Gradle Plugin запускает проверку через
buildHealth. При обнаружении дубликатов DAGP 3.5.0 сравнивает поля и методы классов, включая типы, параметры и модификаторы. Несовместимые сигнатуры помогают найти конфликт версий, ошибочную перепаковку библиотеки или подозрительную подмену класса.
Разбор проверки Gradle-сборки предлагает предупреждать о дубликатах либо останавливать сборку. Ограничение остаётся: вредоносная реализация с прежними сигнатурами пройдёт такую проверку, поэтому DAGP служит ранним сигналом, а не полной защитой.8 313
Как защитить REST API в Spring Boot от несовместимых изменений
В Spring Boot обновление Jackson, смена конфигурации или новая функция могут незаметно нарушить договорённости с клиентами REST API. Контрактные тесты фиксируют ожидаемые запросы и ответы, чтобы поймать расхождение до развёртывания.
Для проверки со стороны провайдера OpenAPI-Diff сравнивает текущую спецификацию со снимком. Метод
isCompatible(), в отличие от строгого isUnchanged(), не отклоняет совместимое добавление новых эндпоинтов.
Spring Cloud Contract хранит контракты в YAML, а Maven-плагин генерирует проверочные тесты и WireMock-заглушки для клиентов. Если команда контролирует потребителей API, можно передать им ведение контракта через Pact. Практический разбор трёх подходов помогает выбрать схему и настроить проверки совместимости.8 313
JDK 26: когда автовекторизации JIT мало и нужен Vector API
JIT превращает циклы Java в SIMD-инструкции, обрабатывающие несколько чисел за раз. На JDK 26.0.2.1 и Apple M4 Max суммирование миллиона элементов ускорилось примерно вдвое. Вклад оптимизации можно проверить JMH-прогоном с
-XX:-UseSuperWord.
Vector API с одним аккумулятором дал те же 113 мкс на операцию, а четыре независимых сократили время до 35 мкс: процессору не пришлось ждать предыдущее сложение.
Сравнение JMH-бенчмарков показывает цену ускорения: Vector API остаётся инкубационным, код усложняется, а выигрыш зависит от CPU. Бенчмарк стоит прогнать на production-сервере.8 313
JDK 25: как передавать контекст запроса через ScopedValue
В JDK 25 ScopedValue стал постоянным API для идентификаторов запросов, данных пользователя и трассировки. Значение привязывается через
where(...).run(...), читается через get() во всей цепочке вызовов и автоматически исчезает после выхода из блока. Это убирает сквозные параметры и ручной ThreadLocal.remove().
Во вложенной области значение можно временно перепривязать. После её завершения внешняя привязка восстановится, поэтому время жизни контекста видно прямо в коде.
Практический пример с RequestContext показывает проверку через isBound() до и после блока. Для миграции ScopedValue подходит читаемому контексту с ограниченным временем жизни. ThreadLocal остаётся для изменяемого состояния потока, прежних версий Java и совместимости с существующими API.8 313
Spring Boot 3.5 и 4: подключаем Fory JSON к MVC и WebFlux
Spring Fory 1.1.0 требует Java 17 или новее. Для Boot 4 предназначен
fory-json-spring-boot-starter, для Boot 3.5 — fory-json-spring-boot3-starter. Стартер выбирает интеграцию для MVC или WebFlux, а контроллеры сохраняют привычные @RequestBody, Mono и Flux.
При миграции настройки придётся перенести явно: аннотации Jackson и параметры spring.jackson.* не управляют Fory. Стоит отдельно проверить имена полей и весь JSON-контракт. Ограничение входных данных в MVC относится ко всему телу запроса, а при потоковом NDJSON в WebFlux — к каждому значению в Flux.
Руководство по интеграции показывает API заказов, настройку преобразования JSON и вариант без Spring Boot. Бенчмарки сериализации не гарантируют такой же прирост HTTP-производительности: результат нужно измерять на своём приложении.8 313
Как убрать временные MemorySegment при доступе к нативной памяти в Java
В горячем цикле обёртка MemorySegment для каждого нативного адреса создаёт короткоживущие объекты и нагружает GC. Разбор арифметики указателей через FFM API показывает другой путь: один глобальный сегмент начинается с адреса 0 и расширяется через
reinterpret до Long.MAX_VALUE.
VarHandle, построенный из описания структуры, получает этот сегмент как базу, а числовой адрес как смещение. Новая обёртка на каждом проходе не нужна. В авторском JMH-тесте такой вариант дал примерно 21 млн против 1,49 млн операций в миллисекунду.
Цена ускорения: глобальный сегмент не проверит, существует ли память по адресу и не была ли она освобождена. Для горячего участка сначала измерьте аллокации и производительность собственным JMH-тестом, а время жизни памяти контролируйте отдельно.8 313
Spring Boot 4: как выбрать режим RestTestClient для проверки REST API
Новый RestTestClient позволяет сохранить один способ вызова API и менять охват теста. Клиент привязывается к контроллеру для модульного теста, к MockMvc для проверки валидации и Spring Security, к WebApplicationContext для интеграционного теста либо к запущенному серверу для сквозной проверки по HTTP.
При привязке к контроллеру Spring-контекст не поднимается: зависимости нужно создать или подменить самостоятельно, а валидация бинов и безопасность не проверяются. В примере
@AuthenticationPrincipal получает объект с полями null, если не зарегистрировать собственный обработчик аргумента. Это ограничение данного режима и конфигурации теста.
Разбор четырёх режимов RestTestClient показывает настройку клиента и проверки ответа API. Для подключения нужен тестовый модуль spring-boot-starter-webmvc-test.8 313
Java 25 и Micronaut: упрощаем точку входа через compact source file
В Java 25 механизм compact source files финализирован в JEP 512. Он позволяет запускать программу без явного объявления класса и метода
public static void main. Для Micronaut точка входа сокращается до импорта, void main() и вызова Micronaut.run().
Меняется и Gradle: вместо полного имени com.example.Application в mainClass достаточно Application. Неявный класс получает имя файла, поэтому Application.java и значение mainClass должны совпадать точно.
Для существующего проекта это локальное упрощение стартового кода, но структуру исходников придётся проверить: файл без объявления пакета лучше держать в корне src/main/java, иначе IDE и инкрементальная компиляция могут работать хуже. В примере с конфигурацией Gradle показаны оба варианта точки входа.8 313
Как проверить отправку Kafka-сообщения в Spring Boot без Docker
В интеграционном тесте с Embedded Kafka настоящий брокер запускается внутри тестового процесса. Аннотация
@EmbeddedKafka создаёт топик greetings, поэтому внешняя Kafka и Docker не нужны.
KafkaTemplate публикует сообщение, а отдельный KafkaConsumer получает запись через KafkaTestUtils.getSingleRecord. Перед отправкой тест считывает сообщения, созданные ApplicationRunner при запуске, чтобы проверка не забрала старую запись.
Тест подтверждает доставку от продюсера до брокера и обратно к потребителю, но не результат работы метода с @KafkaListener. Эффект обработчика стоит проверять отдельно: так транспортная интеграция и бизнес-логика не маскируют ошибки друг друга.8 313
Gradle 9.5.1 в одноразовом CI: сокращаем запуск сборки
В свежем CI-контейнере нет состояния предыдущего запуска, поэтому Gradle снова получает дистрибутив и готовит служебные файлы. Для Java-проекта это лишнее время до выполнения задач сборки.
В разборе запуска Gradle проверяют три приёма: использовать дистрибутив
-bin вместо -all, восстанавливать каталоги Wrapper и заранее готовить generated-gradle-jars вместе с jars-9. Версии образа и Wrapper нужно согласовать, а после обновления Gradle пересобрать подготовленный образ и проверить пути кэша.
Результаты служат ориентиром: небольшой Spring Boot-проект собирали в чистом Docker-окружении по пять раз, базовый прогон занял 31,7 секунды. Повторите замеры на своей кодовой базе: в крупной сборке больше времени могут отнимать зависимости, конфигурация или выполнение задач.8 313
Vaadin и Spring: как собрать интерактивный Java-интерфейс
Во второй части проекта NeuroWatch интерфейс на Vaadin дополняют диалогами, формой с валидацией и обновлением данных в реальном времени. Приложение использует Spring Security, Kafka и MongoDB.
Выбор строки в таблице открывает карточку: метаданные размещены в FormLayout, связанные записи — во вложенном Grid. Вкладки позволяют добавить форму редактирования, а Binder связывает её поля с Java-объектом и проверками.
Редактирование показывают только пользователям с ролью ADMIN. При этом проверка роли в интерфейсе не защищает данные сама по себе: ограничения нужно повторить на уровне сервисов и репозиториев.
Схема диалогов, форм и обновлений пригодится для Spring-приложений, где серверный Java-код управляет состоянием интерфейса.
8 313
HotSpot: как задачи JIT задерживают выгрузку ClassLoader
JIT создаёт для горячего метода задачу CompileTask: она держит ссылку на метод, класс и его загрузчик. Пока поток C1 или C2 не завершит компиляцию, GC не выгрузит загрузчик.
Поэтому тест после
System.gc() может срабатывать нестабильно. Повторный полный GC иногда мешает компиляторам закончить работу.
Для диагностики дайте JIT время либо отключите фоновую компиляцию флагом -XX:-BackgroundCompilation. Это делает удаление задач предсказуемее, но добавляет скачки задержки. Тест с URLClassLoader и PhantomReference показывает этот сценарий.8 313
Как ускорить агрегацию в Spring Batch с помощью DuckDB
В Spring Batch агрегацию миллионов строк можно вынести из Java-цикла с HashMap в SQL-запрос DuckDB внутри Tasklet.
В тесте на Java 21 и DuckDB 1.5.5: 10 млн строк обработались за 0,17 секунды вместо 1, 50 млн — за 0,61 вместо 4,83. На свежем запуске JVM влияет прогрев JIT, поэтому результаты лучше перепроверить на своих данных.
Схема интеграции и исходный код пригодятся для агрегаций и соединений. Классическую обработку оставьте для внешних вызовов и обогащения каждой строки.
8 313
Как перевести сборку Gradle на Isolated Projects
Isolated Projects параллельно конфигурирует проекты, ускоряя локальные сборки и синхронизацию IntelliJ IDEA. Функция экспериментальная и требует совместимости с Configuration Cache.
Команда Gradle начала с
help, собрала нарушения в диагностическом отчёте и затем проверила IDE и CI. Плагины соглашений изолировали логику проектов, а обмен артефактами шёл через зависимости.
Опыт внедрения команды Gradle показывает порядок миграции: сначала локальные сборки, затем CI. Продакшен-артефакты пока собирают без этой функции, пока не подтверждена корректность результатов.