Причины перехода на Java 25

Java 25 — это релиз с долгосрочной поддержкой (LTS), поэтому он является естественным выбором для команд, которые сейчас используют Java 8, 11, 17 или 21. Каждый выпуск LTS получает годы обновлений и исправлений безопасности, поэтому переход к Java 25 позволяет приложениям поддерживать, защищать и использовать последние улучшения производительности и языка.

Вопрос не в том, если вы должны перейти к более новому выпуску LTS, но когда. Чем дольше вы ожидаете, тем больше изменений накапливается между текущей версией и следующей поддерживаемой. Есть четкие преимущества перехода на Java 25, и планирование перемещения раньше, чем позже снижает риск.

Начиная с Java 8, в каждом выпуске появлялись новые возможности и улучшения. Существуют заметные дополнения и изменения в API, а также улучшения времени запуска, пропускной способности, использования памяти, масштабируемости и производительности разработчика. В этой статье рассматриваются самые важные изменения, с акцентом на Java версии, предоставляемые с момента выпуска Java 11 LTS: Java 17, Java 21 и Java 25.

Переход на Java 25

Вы можете перейти на Java 25 в пошаговой форме. Код, разработанный и созданный с помощью более старого JDK, обычно может работать на Java 25 без повторной компиляции. Как и при любом крупном обновлении, следите за удаленными API, устаревшими пакетами, использованием внутренних API и изменениями поведения по умолчанию, особенно вокруг сборки мусора.

Если вы идете с Java 8 или 11, начните с перехода с Java 8 на Java 11 руководства, чтобы решить самый большой набор критических изменений, а затем продолжить переход к Java 17, 21 и 25. Если вы уже используете Java 17 или 21, переход на Java 25 обычно оказывается проще, поскольку система модулей и большинство изменений платформы уже остались позади.

Tip

Модернизация GitHub приложение Copilot поможет оценить приложение, запланировать обновление и автоматически применить изменения кода. Он поддерживает обновление между версиями Java 8, 11, 17, 21 и 25, выполняет сборку и тестирование проекта после каждого изменения и помогает устранять проблемы, вызванные изменениями в поведении, описанными далее в этой статье.

Tip

Флаги JVM, настроенные для более старой версии JDK, могут стать устаревшими, удаленными или неоптимальными на Java 25. Вместо переноса устаревших параметров можно позволить средству запуска команд Azure для Java (jaz) применять флаги JVM, адаптированные к версии JDK и ресурсам контейнера или виртуальной машины. Замените команду java на jaz в вашем скрипте запуска или в Dockerfile, чтобы воспользоваться этим.

Высокоуровневые изменения с Java 11

Этот раздел не перечисляет все изменения, внесенные с Java 8. Он выделяет изменения, которые оказывают наибольшее влияние на производительность, масштабируемость, диагностику, производительность и безопасность. Большинство этих возможностей появились в выпусках Java 17, 21 и 25 и теперь входят в базовый уровень LTS, доступный в Java 25. Каждая функция отмечает выпуск Java, в котором она была интегрирована.

Масштабируемость с помощью виртуальных потоков

Виртуальные потоки [1] — это упрощенные потоки, управляемые JVM, а не операционной системой, что значительно снижает затраты на запись и выполнение одновременных приложений с высокой пропускной способностью. С помощью виртуальных потоков можно писать код в простой модели «один поток на запрос» и при этом поддерживать большое число одновременных операций, что идеально подходит для микросервисов, ограниченных операциями ввода-вывода, и нагрузок типа «запрос-ответ».

Виртуальные потоки были завершены в Java 21. Java 24 устранила ключевое ограничение, позволив виртуальным потокам синхронизироваться без закрепления за потоками-носителями [2], что улучшает масштабируемость кода, использующего блоки synchronized.

Структурированная конкурентность и значения с ограниченной областью видимости

Области значений [3] обеспечивают безопасный, эффективный способ совместного использования неизменяемых данных внутри и между потоками, включая виртуальные потоки. Это современная альтернатива потоково-локальным переменным, которая хорошо сочетается с моделью «один поток на задачу».

Структурированная конкурентность [4] трактует группы связанных параллельно выполняемых задач как единое целое, что упрощает обработку ошибок и отмену. Впервые представленная в Java 21, эта функция продолжает развиваться и естественно сочетается с виртуальными потоками.

Производительность языка

Серия улучшений языка, предоставляемых в Java 14–Java 25, делает код более кратким, безопасным и удобным для чтения:

  • Переключение выражений [5] (Java 14) позволяет возвращать switch значение и использовать более чистый синтаксис со стрелками.
  • Сопоставление шаблонов для instanceof [6] (Java 16) удаляет необходимость явных приведения после проверки типа.
  • Записи [7] (Java 16) представляют неизменяемые данные как прозрачные носители фиксированного набора значений, уменьшая объём шаблонного кода.
  • Запечатанные классы [8] (Java 17) позволяют управлять расширением или реализацией типа.
  • Текстовые блоки [9] (Java 15) упрощают многостроальные строковые литералы.
  • Сопоставление шаблонов для switch [10] (Java 21) и шаблоны записей [11] (Java 21) позволяют выразить сложную условную логику и деструкцию данных четко и безопасно.
  • Последовательность коллекций [12] (Java 21) добавляет универсальный API для коллекций с определенным порядком встречи, включая доступ к первым и последним элементам.
  • Неименованные переменные и шаблоны [13] (Java 22) позволяют явно пометить неиспользуемые переменные и компоненты шаблона.
  • Объявления импорта модуля [14] (Java 25) позволяют импортировать экспортированные пакеты всего модуля с одним объявлением.
  • Компактные исходные файлы и основные методы экземпляра [15] (Java 25) сокращают церемонию, необходимую для небольших программ, что делает Java проще учиться и быстрее прототипа.
  • Гибкие тела конструктора [16] (Java 25) позволяют выполнять инструкции перед вызовом super(...) илиthis(...), что улучшает проверку и инициализацию.

Производительность и запуск

Несколько изменений среды выполнения повышают пропускную способность, объем памяти и время запуска:

  • Заголовки компактных объектов [17] (Java 25) снижают размер заголовков объектов на 64-разрядных платформах. Это уменьшение снижает потребление памяти в куче и может повысить производительность в сценариях с интенсивным выделением памяти.
  • Совместное использование данных классов (CDS) сокращает время запуска за счёт проецирования архивированных классов в память во время выполнения. Архивы CDS по умолчанию [18] (Java 12) и динамические архивы CDS [19] (Java 13) упрощают внедрение этой функции без ручного обучения.
  • Предварительная загрузка и связывание классов [20] (Java 24), вместе с предварительной эргономикой командной строки [21] (Java 25) и предварительным профилированием методов [22] (Java 25), сокращают время запуска и прогрева за счёт повторного использования результатов работы, сохранённых в архиве приложения. Эти функции являются частью инициативы Project Leyden, направленной на ускорение запуска Java.

Эти улучшения особенно полезны для облачных и бессерверных рабочих нагрузок, где быстрый запуск и небольшой объем ресурсов напрямую преобразуются в более эффективное масштабирование и снижение затрат.

Сборка мусора

Java 25 поставляется со зрелыми сборщиками мусора с низкими паузами, подходящими для широкого спектра рабочих нагрузок:

  • ZGC [23] (Java 15) и Shenandoah [24] (Java 15) — это готовые к промышленной эксплуатации сборщики, разработанные для минимального времени пауз при работе с большими кучами.
  • G1GC остается сборщиком по умолчанию и продолжает получать улучшения, включая закрепление регионов [25] (Java 22) для более плавного взаимодействия с нативным кодом.
  • Поколение ZGC [26] (Java 21) повышает эффективность, сохраняя отдельные поколения. По состоянию на Java 23, ZGC по умолчанию работает в поколенческом режиме [27], а непоколенческий режим был удалён в Java 24.
  • Поколенческий Shenandoah [28] (Java 25) добавляет к сборщику Shenandoah поколенческий режим для повышения пропускной способности и устойчивости в условиях нехватки памяти.

JVM задает параметры GC по умолчанию для среднего варианта использования. Настройте эти значения по умолчанию и другие параметры GC для оптимизации пропускной способности или задержки в соответствии с требованиями приложения.

Tip

Сборщик мусора по умолчанию и многие значения по умолчанию JVM отличаются в Java версиях, поэтому параметры, настроенные для Java 8 или 11, больше не будут оптимальными для Java 25. Средство запуска команд Azure для Java (jaz) считывает ограничения памяти и ЦП контейнера и применяет флаги JVM, адаптированные к версии и среде JDK автоматически.

Диагностика и наблюдаемость

Диагностика была улучшена от выпуска к выпуску, как в самом языке, так и в Java Flight Recorder (JFR):

  • Полезные исключения NullPointerException [29] (Java 14) точно указывают, какая переменная имела значение null, что ускоряет отладку.
  • Потоковая передача событий JFR [30] (Java 14) позволяет инструментам непрерывно получать данные профилирования и диагностики вместо их чтения из файла дампа.
  • Профилирование JFR по процессорному времени [31] (Java 25) добавляет экспериментальное профилирование методов на основе процессорного времени в Linux.
  • Совместная выборка JFR [32] (Java 25) повышает стабильность выборки стека.
  • Время и трассировка метода JFR [33] (Java 25) позволяет отслеживать определенные методы без изменения кода приложения.

Безопасность и криптография

Java 25 укрепляет состояние безопасности платформы, в том числе подготовку к пост-квантовому миру:

  • Edwards-Curve алгоритм цифровой подписи (EdDSA) [34] (Java 15) добавляет современную высокопроизводительную схему подписи.
  • API механизма инкапсуляции ключа [35] (Java 21) предоставляет стандартный API для алгоритмов KEM.
  • Криптография, устойчивая к квантовым вычислениям включает стандартные реализации механизма инкапсуляции ключей, основанного на модульных решётках (ML-KEM) [36] (Java 24), и алгоритма цифровой подписи (ML-DSA) [37] (Java 24).
  • API функции вывода ключей [38] (Java 25) предоставляет стандартный API для функций вывода ключей.

Нативная совместимость

API внешней функции и памяти [39] (Java 22) предоставляет безопасный, эффективный и чистый Java способ вызова собственных библиотек и доступа к собственной памяти. Это современная замена Java Native Interface (JNI), которая уменьшает объём шаблонного кода и повышает безопасность.

Инструменты и библиотеки

Несколько дополнений улучшают повседневную разработку и сокращают потребность в сторонних средствах:

  • Средство упаковки (jpackage) [40] (Java 16) создает нативные установщики и пакеты для Java-приложений.
  • Простой веб-сервер [41] (Java 18) предоставляет минимальный статический HTTP-сервер для создания прототипов и тестирования.
  • Расширенные генераторы псевдорандомных чисел [42] (Java 17) добавляют новые интерфейсы и реализации для случайного создания чисел.

Изменения в поведении, которые следует учитывать

Некоторые изменения с Java 11 изменяют поведение по умолчанию, поэтому перед обновлением просмотрите их:

  • Строгая инкапсуляция внутренних компонентов JDK [43] (Java 17) по умолчанию блокирует рефлексивный доступ к большинству внутренних API. Код или библиотеки, которые обращаются к sun.* или другим внутренним пакетам, могут потребовать обновления.
  • UTF-8 по умолчанию [44] (Java 18) делает UTF-8 набором символов по умолчанию для стандартных api Java. Приложения, зависящие от конкретной платформы, могут вести себя по-разному.
  • Finalization объявлена устаревшей и подлежит удалению [45] (Java 18) указывает на то, что finalize() со временем будет удалён. Перейдите на tryс ресурсами или java.lang.ref.Cleaner.
  • Подготовка к запрету динамической загрузки агентов [46] (Java 21) предупреждает, когда агент загружается в запущенный JVM. Для некоторых средств мониторинга и инструментирования может потребоваться изменение конфигурации.

Tip

Модернизация GitHub приложение Copilot помогает оценить и исправить эти изменения поведения автоматически при обновлении.

Контейнеры и облако

Поддержка контейнеров в JVM, введённая для Docker и других контейнерных сред выполнения, продолжает совершенствоваться. JVM считывает ограничения процессора и памяти, заданные контрольными группами (cgroups) контейнера, и соответствующим образом определяет размер кучи и других ресурсов. В сочетании с более быстрым запуском, меньшим объемом ресурсов и виртуальными потоками, Java 25 хорошо подходит для контейнерных и бессерверных развертываний на Azure.

Если вы запускаете рабочие нагрузки Java на Azure контейнерах или виртуальных машинах, средство запуска команд Azure для Java (jaz) может применять оптимизированные для облака версии параметры JVM по умолчанию.

Дальнейшие действия

Ссылки

[1] Oracle Corporation, "JEP 444: Виртуальные нити". [Электронный ресурс]. Доступно: https://openjdk.org/jeps/444.

[2] Oracle Corporation, "JEP 491: синхронизация виртуальных потоков без закрепления". (в Интернете). Доступно: https://openjdk.org/jeps/491.

[3] Oracle Corporation, "JEP 506: область значений". (в Интернете). Доступно: https://openjdk.org/jeps/506.

[4] Oracle Corporation, "JEP 453: структурированный параллелизм (предварительная версия)." (Онлайн). Доступно: https://openjdk.org/jeps/453.

[5] Oracle Corporation, "JEP 361: switch Expressions". (в Интернете). Доступно: https://openjdk.org/jeps/361.

[6] Oracle Corporation, "JEP 394: Сопоставление шаблонов для экземпляра". (в Интернете). Доступно: https://openjdk.org/jeps/394.

[7] Oracle Corporation, "JEP 395: Records". (в Интернете). Доступно: https://openjdk.org/jeps/395.

[8] Oracle Corporation, "JEP 409: запечатанные классы". (в Интернете). Доступно: https://openjdk.org/jeps/409.

[9] Oracle Corporation, "JEP 378: текстовые блоки". (в Интернете). Доступно: https://openjdk.org/jeps/378.

[10] Oracle Corporation, "JEP 441: Сопоставление шаблонов для переключения". (в Интернете). Доступно: https://openjdk.org/jeps/441.

[11] Oracle Corporation, "JEP 440: Шаблоны записей". (в Интернете). Доступно: https://openjdk.org/jeps/440.

[12] Oracle Corporation, "JEP 431: Sequenced Collections". (в Интернете). Доступно: https://openjdk.org/jeps/431.

[13] Oracle Corporation, "JEP 456: неименованные переменные и шаблоны". (в Интернете). Доступно: https://openjdk.org/jeps/456.

[14] Oracle Corporation, "JEP 511: объявления импорта модулей". (в Интернете). Доступно: https://openjdk.org/jeps/511.

[15] Oracle Corporation, "JEP 512: компактные исходные файлы и основные методы экземпляра". (в Интернете). Доступно: https://openjdk.org/jeps/512.

[16] Oracle Corporation, "JEP 513: гибкие тела конструкторов". (В Интернете). Доступно: https://openjdk.org/jeps/513.

[17] Oracle Corporation, "JEP 519: Compact Object Headers". (в Интернете). Доступно: https://openjdk.org/jeps/519.

[18] Oracle Corporation, "JEP 341: архивы CDS, используемые по умолчанию". (Онлайн). Доступно: https://openjdk.org/jeps/341.

[19] Oracle Corporation, "JEP 350: Dynamic CDS Archives". (в Интернете). Доступно: https://openjdk.org/jeps/350.

[20] Oracle Corporation, "JEP 483: Опережающая загрузка и связывание классов." (Онлайн). Доступно: https://openjdk.org/jeps/483.

[21] Oracle Corporation, "JEP 514: Эргономика командной строки для опережающей компиляции." (Онлайн). Доступно: https://openjdk.org/jeps/514.

[22] Oracle Corporation, "JEP 515: предварительное профилирование метода". (в Интернете). Доступно: https://openjdk.org/jeps/515.

[23] Oracle Corporation, «JEP 377: ZGC: масштабируемый сборщик мусора с низкой задержкой». (Онлайн). Доступно: https://openjdk.org/jeps/377.

[24] Oracle Corporation, "JEP 379: Shenandoah: сборщик мусора с низким временем пауз". (Онлайн). Доступно: https://openjdk.org/jeps/379.

[25] Oracle Corporation, "JEP 423: закрепление регионов в G1". (Онлайн). Доступно: https://openjdk.org/jeps/423.

[26] Oracle Corporation, "JEP 439: Generational ZGC". (в Интернете). Доступно: https://openjdk.org/jeps/439.

[27] Oracle Corporation, "JEP 474: ZGC: поколенческий режим по умолчанию." (Онлайн). Доступно: https://openjdk.org/jeps/474.

[28] Oracle Corporation, "JEP 521: Generational Shenandoah". (в Интернете). Доступно: https://openjdk.org/jeps/521.

[29] Oracle Corporation, "JEP 358: Полезные исключения NullPointerException". (Онлайн). Доступно: https://openjdk.org/jeps/358.

[30] Oracle Corporation, "JEP 349: JFR Event Streaming". (в Интернете). Доступно: https://openjdk.org/jeps/349.

[31] Oracle Corporation, "JEP 509: JFR профилирование времени ЦП (экспериментальное)." (Онлайн). Доступно: https://openjdk.org/jeps/509.

[32] Oracle Corporation, "JEP 518: кооперативная выборка JFR". (Онлайн). Доступно: https://openjdk.org/jeps/518.

[33] Oracle Corporation, "JEP 520: JFR Method Timing и Tracing". (в Интернете). Доступно: https://openjdk.org/jeps/520.

[34] Oracle Corporation, "JEP 339: Edwards-Curve алгоритм цифровой подписи (EdDSA)." (в Интернете). Доступно: https://openjdk.org/jeps/339.

[35] Oracle Corporation, "JEP 452: API механизма инкапсуляции ключей." (Онлайн). Доступно: https://openjdk.org/jeps/452.

[36] Oracle Corporation, "JEP 496: квантовоустойчивый механизм инкапсуляции ключей на основе модульных решёток". (Онлайн). Доступно: https://openjdk.org/jeps/496.

[37] Oracle Corporation, "JEP 497: Квантовоустойчивый алгоритм цифровой подписи, основанный на модульных решётках". (Онлайн). Доступно: https://openjdk.org/jeps/497.

[38] Oracle Corporation, "JEP 510: API функции вывода ключей". (в Интернете). Доступно: https://openjdk.org/jeps/510.

[39] Oracle Corporation, "JEP 454: Внешние функции и API памяти". (в Интернете). Доступно: https://openjdk.org/jeps/454.

[40] Oracle Corporation, "JEP 392: средство упаковки". (в Интернете). Доступно: https://openjdk.org/jeps/392.

[41] Oracle Corporation, "JEP 408: простой веб-сервер". (в Интернете). Доступно: https://openjdk.org/jeps/408.

[42] Oracle Corporation, "JEP 356: улучшенные генераторы псевдослучайных чисел." (Онлайн). Доступно: https://openjdk.org/jeps/356.

[43] Oracle Corporation, "JEP 403: Строгая инкапсуляция внутренних компонентов JDK." (Онлайн). Доступно: https://openjdk.org/jeps/403.

[44] Oracle Corporation, "JEP 400: UTF-8 по умолчанию". (в Интернете). Доступно: https://openjdk.org/jeps/400.

[45] Oracle Corporation, "JEP 421: нерекомендуемая финализация для удаления". (в Интернете). Доступно: https://openjdk.org/jeps/421.

[46] Oracle Corporation, "JEP 451: подготовка к запрету динамической загрузки агентов". (в Интернете). Доступно: https://openjdk.org/jeps/451.