Java 21, выпущенная как версия с долгосрочной поддержкой (LTS), предлагает важные штуки для улучшения в производительности, синтаксисе, параллелизме и секьюрностью по сравнению с Java 17. Но обновление - это не просто замена версии JDK. Существуют очень важные проверки совместимости и изменения в функциональности, которые необходимо учесть, чтобы избежать неожиданных проблем во время выполнения и получения по ж**е от тимлида.

Что вам нужно знать перед переходом с Java 17 на Java 21
Поговорим в статье про важные штуки, которые нужно учитывать при обновлении: изменения, что нарушает совместимость, обновлённое поведение JVM, совместимость библиотек и как смигрироваться без боли
Зачем обновляться с Java 17 на Java 21?
- Java 21 - следующая LTS-версия после Java 17, c поддержкой до 2029 года (и даже позже)
- Повышенная производительность (например, новые опции GC, такие как Generational ZGC)
- Современные синтаксические возможности (шаблоны записей, pattern matching в switch и другие штуки)
- Улучшенная работа с потоками благодаря Project Loom (виртуальные потоки)
- Скажем, улучшенный API (жёсткая инкапсуляция, запечатанные классы)
Изменения и советы как мигрироваться
1. Больше ограничений на внутренние API
Java продолжает усиливать модульные границы. Доступ к внутренним компонентам JDK, таким как sun.misc.Unsafe или sun.reflect.*, теперь невозможен без явного разрешения.
Решение:
Используйте jdeps для обнаружения использования внутренних API:
jdeps --jdk-internals your-app.jar
Рекомендуемые альтернативы:
- VarHandle вместо Unsafe
- MethodHandles для отражённого доступа
- Обновите сторонние библиотеки, использующие внутренние API
2. Изменено поведение JVM и дефолтное значение для GC
Рекомендации:
- Проверьте пользовательские параметры JVM (-XX:+...) на совместимость
- Проверьте использование ZGC для приложений с низкой задержкой
- Тестаните производительность в контейнерах с включённым CDS
3. Усилены ограничения системы модулей
Жёсткая (не такая как ваш начальник) инкапсуляция в Java Platform Module System (JPMS) может привести к сбоям при нелегальном отражённом доступе.
Решения:
Добавьте необходимые экспорты:
--add-exports java.base/sun.security.util=ALL-UNNAMED
- По возможности переходите на публичные, поддерживаемые API
4. Устаревшие или удалённые API
Java 21 удаляет или дизейблит ряд устаревших API интерфейсов
5. Эволюция или финализация preview-функций
Если вы используете preview-функции, такие как шаблоны записей или pattern matching для switch, их синтаксис и поведение могут быть слегка другими в Java 21
Обновлённые JEP:
При компиляции или запуске кода с preview-функциями используйте:
--enable-preview
Рекомендуемые улучшения (на ваше лягушачее усмотрение)
1. Чище синтаксис и DTO
- Комбинируйте record и pattern matching для красивого кода
- Используйте var и деструктуризацию для сокращения шаблонного кода
2. Новый уровень параллелизма
- Применяйте StructuredTaskScope или виртуальные потоки для читаемого асинхронного кода
- Попробуйте Project Loom для многопоточных приложений
3. Прирост производительности
- Используйте ZGC или Generational ZGC для больших heap-ов
- Применяйте Class Data Sharing (CDS) для ускорения запуска
- Чекните Foreign Function & Memory API (JEP 442) вместо JNI
Итак, чеклист
Что делать? | Обязательно? | Как сделать ИЛИ Совет |
---|---|---|
Проверить использование внутренних API | ✅ | jdeps |
Проверить флаги JVM и настройки GC | ✅ | Сравнить с -XX:+PrintFlagsFinal |
Обновить зависимости (Spring, Netty) | ✅ | Проверить официальные списки совместимости |
Проверить совместимость preview-функций | ⭕ | Использовать --enable-preview |
Перекомпиляция с использованием Java 21 | ✅ | javac --release 21 |
Полный проход тестов на Java 21 | ✅ | Модульные, интеграционные и E2E тесты |
Пример обновления с помощью командной строки
# Проверка использования внутренних JDK API
jdeps --jdk-internals target/your-app.jar
#Компиляция с использованием Java 21
javac --release 21 -d out src/**/*.java
#Запуск с поддержкой preview-функций (на ваше усмотрение)
java --enable-preview -cp out com.example.Main