Выпуск Java SE 22

После шести месяцев разработки компания Oracle выпустила платформу Java SE 22 (Java Platform, Standard Edition 22), в качестве эталонной реализации которой используется открытый проект OpenJDK. За исключением удаления некоторых устаревших возможностей в Java SE 22 сохранена обратная совместимость с прошлыми выпусками платформы Java – большинство ранее написанных Java-проектов без изменений будут работоспособны при запуске под управлением новой версии. Готовые для установки сборки Java SE 22 (JDK, JRE и Server JRE) подготовлены для Linux (x86_64, AArch64), Windows (x86_64) и macOS (x86_64, AArch64). Разработанная в рамках проекта OpenJDK эталонная реализация Java 22 полностью открыта под лицензией GPLv2 с исключениями GNU ClassPath, разрешающими динамическое связывание с коммерческими продуктами.

Java SE 22 отнесён к категории выпусков с обычным сроком поддержки, обновления для которого будут выпускаться до следующего релиза. В качестве ветки с длительным сроком поддержки (LTS) следует использовать Java SE 21 или Java SE 17, обновления для которых будут выпускаться до 2031 и 2029 годов соответственно (общедоступные – до 2028 и 2026 годов). Общедоступная поддержка LTS-ветки Java SE 11 прекращена в сентябре прошлого года, но расширенная поддержка будет осуществляться до 2032 года. Расширенная поддержка LTS-ветки Java SE 8 продлится до 2030 года.

Напомним, что начиная с выпуска Java 10 проект перешёл на новый процесс разработки, подразумевающий более короткий цикл формирования новых релизов. Новая функциональность теперь развивается в одной постоянно обновляемой master-ветке, в которую включаются уже готовые изменения и от которой раз в шесть месяцев ответвляются ветки для стабилизации новых выпусков.

Из новшеств Java 22 можно отметить:

  • В сборщике мусора G1 реализована поддержка закрепления областей (region pinning), позволяющая временно зафиксировать местоположение Java-объектов в памяти, чтобы избежать их перемещения сборщиком мусора и обеспечить безопасную передачу ссылок на эти объекты между Java и нативным кодом. Закрепление позволяет снизить задержки и обойтись без отключения сборки мусора при выполнении критических секций (critical regions) JNI (Java Native Interface) с нативным кодом (во время выполнения данных секций JVM не должен перемещать связанные с ними критические объекты для того чтобы избежать состояний гонки). Закрепление выводит критические объекты из поля зрения сборщика мусора, который может продолжать выполнять чистку незакреплённых областей.
  • Добавлена предварительная возможность, разрешающая указание в конструкторах выражений перед вызовом super(…), используемого для явного вызова конструктора родительского класса из конструктора наследуемого класса, если эти выражения не ссылаются на создаваемый конструктором экземпляр. class Outer { void hello() { System.out.println(“Hello”); } class Inner { Inner() { hello(); super(); } } }
  • Стабилизирован API FFM (Foreign Function & Memory), позволяющий организовать взаимодействие Java-программ с внешними кодом и данными через вызов функций из внешних библиотек и доступ к памяти вне JVM, не прибегая к использованию JNI (Java Native Interface).
  • Включена поддержка безымянных переменных и сопоставлений с шаблоном – вместо неиспользуемых, но необходимых при вызове переменных и шаблонов, теперь можно указывать символ “_”. // было String pageName = switch (page) { case GitHubIssuePage(var url, var content, var links, int issueNumber) -> “ISSUE #” + issueNumber; … }; // теперь можно String pageName = switch (page) { case GitHubIssuePage(_, _, _, int issueNumber) -> “ISSUE #” + issueNumber; };
  • Предложена предварительная реализация API Class-File для разбора, генерации и преобразования файлов с классами Java. ClassFile cf = ClassFile.of(); ClassModel classModel = cf.parse(bytes); byte[] newBytes = cf.build(classModel.thisClass().asSymbol(), classBuilder -> { for (ClassElement ce : classModel) { if (!(ce instanceof MethodModel mm && mm.methodName().stringValue().startsWith(“debug”))) { classBuilder.with(ce); } } });
  • В утилите java реализована возможность запуска Java-программ, поставляемых в форме нескольких файлов с кодом или предкомпилированных библиотек классов, без раздельной компиляции этих файлов и без конфигурирования сборочной системы. Новая возможность упрощает запуск программ, в которых код разных классов выделен в отдельные файлы. Prog.java: class Prog { public static void main(String[] args) { Helper.run(); } } Helper.java: class Helper { static void run() { System.out.println(“Hello!”); } }

    Например, для запуска программы, состоящей из двух файлов “Prog.java” и “Helper.java” теперь достаточно запустить “java Prog.java”, что приведёт к компиляции класса Prog, определения ссылки на класс Helper, поиска и компиляции файла Helper.java и вызова метода main.

  • Добавлена вторая предварительная реализация строковых шаблонов (String Template), реализованных в дополнение к строковым литералам и блокам текста. Строковые шаблоны позволяют совмещать текст с вычисляемыми выражениями и переменными без использования оператора “+”. Подстановка выражений осуществляется при помощи подстановок {..}, при этом для проверки корректности подставляемых значений могут подключаться специальные обработчики. Например, обработчик SQL обеспечивает проверку значений, подставляемых в SQL-код, и возвращает на выходе объект java.sql.Statement, а обработчик JSON отслеживает корректность подстановок JSON и возвращает JsonNode. String query = “SELECT * FROM Person p WHERE p.” + property + ” = ‘” + value + “‘”; // было Statement query = SQL.”””SELECT * FROM Person p WHERE p.{property} = ‘{value}'”””; // стало
  • Добавлена седьмая предварительная реализация API Vector, предоставляющего функции для векторных вычислений, которые выполняются с использованием векторных инструкций процессоров x86_64 и AArch64 и позволяют одновременно применить операции сразу к нескольким значениям (SIMD). В отличие от предоставляемых в JIT-компиляторе HotSpot возможностей по автовекторизации скалярных операций, новый API даёт возможность явно управлять векторизацией для параллельной обработки данных.
  • Добавлена предварительная реализация расширенного API Stream, поддерживающего определение собственных промежуточных операций, которые могут оказаться полезны в случаях, когда существующих встроенных промежуточных операций недостаточно для желаемого преобразования данных. Собственные обработчики подключаются при помощи новой промежуточной операции
    Stream::gather(Gatherer), которая обрабатывает элементы потока, применяя к ним заданный пользователем обработчик. jshell> Stream.of(1,2,3,4,5,6,7,8,9).gather(new WindowFixed(3)).toList() $1 ==> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
  • Предложен для тестирования второй вариант экспериментального API для cтруктурированного параллелизма (Structured Concurrency), упрощающего разработку многопоточных приложений за счёт обработки нескольких задач, выполняемых в разных потоках, как единого блока.
  • Добавлена вторая предварительная реализация неявно объявленных классов и безымянных экземпляров метода “main”, в которых можно обойтись без объявлений public/static, передачи массива аргументов и прочих сущностей, связанных с объявлением класса. // было public class HelloWorld { public static void main(String[] args) { System.out.println(“Hello world!”); } } // теперь можно void main() { System.out.println(“Hello, World!”); }
  • Добавлена вторая предварительная реализация ограниченных значений (Scoped Values), позволяющих совместно использовать неизменяемые данные в потоках и эффективно обмениваться данными между дочерними потоками (значения наследуются). Scoped Values развиваются для замены механизма переменных локальных к потоку (thread-local variables) и более эффективны при использовании очень большого числа виртуальных потоков (тысячи и миллионы потоков). Главное отличие Scoped Values от переменных локальных к потоку в том, что первые записываются один раз, в дальнейшем не могут быть изменены и остаются доступны только на время выполнения потока.
  • В сборщике мусора Parallel повышена производительность работы с большими массивами объектов. Оптимизация позволила в некоторых тестах с большими массивами объектов на 20% снизить задержку перед началом поиска объекта.

Дополнительно можно отметить публикацию обновления платформы для создания приложений с графическим интерфейсом JavaFX 22.

Release. Ссылка here.