InquirerMarcoleta’s remarks on television shown during plunder bail hearingInquirer EntertainmentAJ Raval stars in short film set for international releaseוואלהכתב אישום חמור הוגש נגד הדוקר בבריכה של בן ה-7The Jerusalem PostTrump to review 9/11 victims' request to declassify records on alleged Saudi links to attacksESPNWeek 2 truths: Ohio State's big-game problem; Oregon and Oklahoma still haven't fixed thingsPunchOndo: Police arrest suspected producer of killer herbal drinksХабрБезагентское сканирование безопасности хостов при подключении к сети в NAC-системах. Блажь или необходимость?النهار90% من الجمعية العمومية في لقاء عائلة الجمبازn-tvTeheran weist Riad zurecht : Iran nennt Grund für Absage der Konferenz im Omanسكاي نيوز عربيةقرقاش: الإمارات تبني مكانتها بالإنجاز لا بالسجالاتWirtualna Polska33-latek ścigany ENA zatrzymany. Grozi mu dożywocieNMELil Durk found not guilty of murder for hire
The Daily Newsstand · Free, Always
Monday, September 14, 2026

Java 27: Новый день или Обзор JEP JDK 27

Translate

Уже завтра ожидается выход JDK 27, в которую вошли 9 JEP, связанных с криптографией, диагностическим механизмом JFR, управлением памятью и стандартной библиотекой. В этой статье разберём, что нас ждёт в этом релизе Java.

Как включить фичи в превью и экспериментальной версии

Включить экспериментальные фичи или фичи в превью можно как через командную строку, так и настроить в IDE. Языковые фичи нужно включать на уровне javac, а не только при запуске java.

В командной строке скомпилируйте программу с помощью:

javac --release 27 --enable-preview Main.java

и запустите её с помощью:

java --enable-preview Main

Управление памятью

Разберём 2 JEP, связанных с управлением памятью. Эти фичи повлияют на все приложения, потому что будут включены по умолчанию.

JEP 523: G1 по умолчанию во всех окружениях

В JDK 9 (JEP 248) G1 стал сборщиком мусора по умолчанию для «серверных» окружений. Однако в случаях, когда приложению был доступен один CPU или менее 1792 МБ физической памяти, JVM автоматически выбирала Serial GC.

Раньше это имело смысл: в условиях ограниченных ресурсов Serial GC выигрывал G1 по объёму используемой памяти и пропускной способности. В последние годы G1 сильно доработали (см. JEP 522). Он стал лучше по задержке (latency), объёму используемой нативной памяти (native memory footprint) и пропускной способности, или количеству полезной работы в единицу времени (throughput).

Теперь в JDK 27 (JEP 523), если явно не указать сборщик мусора, то JVM выберет G1 во всех окружениях вне зависимости от числа процессоров и объёма используемой памяти.

Это изменение касается только метрик производительности JVM в условиях ограниченных ресурсов. Вы можете заранее выбрать приложения, на которые нужно обратить внимание, изучив лимиты контейнеров и флаги JVM, которые в них используются. Если приложение работает на Serial GC, и его поведение меняется при переключении на G1, то это повод заранее проверить поведение системы при обновлении версии и при необходимости выставить явное использование Serial GC с помощью -XX:+UseSerialGC.

JEP 534: Компактные заголовки объектов по умолчанию

У каждого объекта в Java есть заголовок, который хранит:

  • mark word, 

  • ссылку на класс,

  • служебные биты JVM.

Идея JEP — уменьшить размер заголовка объекта с 96 до 64 бит на 64-битных архитектурах. Это снизит потребление кучи (heap) и повысит плотность размещения объектов.

Компактные заголовки объектов (Compact Object Headers) появились в JDK 24 (JEP 450) как экспериментальная возможность. Чтобы оценить эффект, нужно было явно включить соответствующий JVM-флаг:

$ java -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders ...

В JDK 25 (JEP 519) они уже перешли в продуктовую возможность. Специальный флаг не требовался, было достаточно следующего:

$ java -XX:+UseCompactObjectHeaders ...

В JDK 27 компактные заголовки объектов становятся фичей по умолчанию в HotSpot JVM на 64-битных архитектурах.

Главный плюс — экономия 20% памяти. по статистике реальных приложений. не нужно переписывать код приложения и вносить какие-либо изменения в поведение объектов. Внутри JVM объект может занимать меньше памяти за счёт более компактного заголовка. Это полезно для приложений, где много маленьких объектов.

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

В JEP приводятся следующие результаты тестирования на бенчмарках:

  • SPECjbb2015: до 22% меньше использования кучи и до 8% меньше CPU time.

  • SPECjbb2015: до 15% меньше GC с G1 и Parallel GC.

  • JSON parser benchmark: до 10% быстрее.

Если у приложения обнаружатся проблемы при использовании компактных заголовков, то отключите их с помощью флага -XX:-UseCompactObjectHeaders:

$ java -XX:-UseCompactObjectHeaders ...

Для сервисов с большим количеством мелких объектов это одна из самых практичных фич JDK 27.


Кстати говоря, мы делаем компактные контейнеры Axiom Runtime Container. По их использованию мы видим, что пользователи зачастую запускают их с довольно ограниченными ресурсами. На что обратить внимание и как спасаться мы уже рассказали, а увидеть эффект (положительный или отрицательный) зачастую можно при помощи JFR, но о нём чуть позже.

Криптография

JEP 527: Постквантовый гибридный обмен ключами в TLS 1.3

Версии TLS меньше 1.3 небезопасны, и не поддерживаются многими сетевыми библиотеками. Если вы ещё не используете TLS 1.3, то уже пора (возможно, потребуется свежий апдейт, если вы на JDK 8).

В этом JEP добавляется поддержка гибридных алгоритмов обмена ключами для TLS 1.3.

Идея в том, чтобы защититься от сценария «harvest now, decrypt later», при котором злоумышленник записывает зашифрованный трафик сейчас, а расшифровать попытается позже, когда появятся достаточно мощные квантовые компьютеры. Этот сценарий подходит для данных, которые будут актуальны следующие 5-10 лет и более, например, медицинские или персональные данные, финансовые документы и коммерческие контракты.

При гибридной схеме обмена ключами используются два и более алгоритма разных групп: классические алгоритмы и алгоритмы следующего поколения.

Классические алгоритмы широко используются на практике, но в будущем могут быть признаны устаревшими. В контексте TLS 1.3 это:

  • эллиптический Диффи — Хеллман на кривых secp256r1 или x25519,

  • Диффи — Хеллман над конечными полями.

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

Цель гибридной схемы обмена ключами — получить итоговый ключ сессии, который будет безопасным до тех пор, пока хотя бы один из используемых алгоритмов обмена ключами останется не взломан.

JEP добавляет три гибридные TLS 1.3 named groups, которые комбинируют ECDHE и ML-KEM:

  • X25519MLKEM768       = X25519 + ML-KEM-768

  • SecP256r1MLKEM768    = secp256r1 + ML-KEM-768

  • SecP384r1MLKEM1024   = secp384r1 + ML-KEM-1024

Если сервер поддерживает гибридный обмен ключами, то Java-клиент сможет использовать его автоматически при условии, что в приложении не ограничены TLS named groups вручную.

import java.net.URI;

import java.net.http.HttpClient;

import java.net.http.HttpRequest;

import java.net.http.HttpResponse;

public class ClientExample {

    public static void main(String[] args) throws Exception {

        HttpClient client = HttpClient.newHttpClient();

        HttpRequest request = HttpRequest.newBuilder()

                .uri(URI.create("https://example.com"))

                .GET()

                .build();

        HttpResponse<String> response =

                client.send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println(response.statusCode());

    }

}

При переходе на JDK 27 в примере выше код менять не нужно.

Если в коде у вас явно заданы named groups, например:

-Djdk.tls.namedGroups="x25519,secp256r1,secp384r1"

То фича работать не будет, так как вы ограничили список named groups только классическими алгоритмами.

В JDK 27 первым в списке предпочтений TLS 1.3 named groups назначен X25519MLKEM768. Полный порядок описан в самом JEP 527. Java-клиент сначала предложит гибридную схему X25519MLKEM768, а затем классические варианты. X25519MLKEM768 выбран как самый быстрый из гибридных вариантов, т.к. Его чаще всего включают TLS-клиенты по умолчанию.

Вы также можете выбрать алгоритмы через SSLParameters::setNamedGroups при настройке соединения TLS-сокета:

SSLSocket tlsSock = (SSLSocket)(SSLContext.getDefault().

                                getSocketFactory().createSocket());

SSLParameters params = tlsSock.getSSLParameters();

params.setNamedGroups(new String[] {

    "SecP256r1MLKEM768", "X25519MLKEM768", "secp256r1", "x25519"

});

tlsSock.setSSLParameters(params);

JEP 538: PEM-кодирование криптографических объектов  (третье превью)

PEM API — API для кодирования криптографических объектов в формат PEM (Privacy-Enhanced Mail) и их декодирования обратно в объекты.

Это API появилось в Java 25 (JEP 470) в превью, осталось на второе превью в Java 26 (JEP 524) и на третье в Java 27 (JEP 538).

Есть несколько изменений в API:

  • Класс PEM теперь является обычным классом, а не record. В него добавили конструкторы, которые принимают Base64-кодированное содержимое в виде массивов байтов. Для некоторых сценариев это удобнее.

  • Интерфейс DEREncodable переименован в BinaryEncodable, чтобы точнее описывать бинарные данные, которые хранятся в PEM-тексте.

  • В класс EncryptedPrivateKeyInfo добавили методы getKeyPair, которые расшифровывают PKCS#8-кодированный текст, содержащий PublicKey.

  • Методы getKey и getKeyPair класса EncryptedPrivateKeyInfo, которые раньше принимали пароль и Provider, теперь принимают только Key.

  • Метод withFactory PEMDecoder переименован в withFactoriesOf, чтобы лучше отражать, что фабрики ключей и сертификатов получаются из переданного Provider.

  • Добавлен новый класс CryptoException, который сигнализирует об ошибках криптографической обработки во время выполнения.

JFR

JEP 536: Редактирование чувствительных данных внутри JFR

Java Flight Recorder — один из самых полезных инструментов диагностики JVM, который даёт понять, как стартовала JVM, какие были флаги, что происходило с GC, потоками, аллокациями и др.

JFR-записи часто содержат данные о запуске процесса:

  • аргументы командной строки,

  • свойства системы,

  • переменные окружения,

  • параметры JVM,

  • параметры приложения.

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

$ export ACCESS_TOKEN=SECRET_TOKEN

$ java -XX:StartFlightRecording:filename=dump.jfr \

       -Xmx2G \

       -Djavax.net.ssl.keyStorePassword=SECRET_PASSWORD \

       -jar application.jar \

      --dbpassword ANOTHER_SECRET_PASSWORD

В старом поведении в файле dump.jfr могли оказаться значения ACCESS_TOKEN, javax.net.ssl.keyStorePassword и --dbpassword.

dump.jfr потом отправляют в поддержку (мы сами часто используем этот инструмент в работе поддержки с клиентами), прикладывают к тикету или кладут в общее хранилище. Из-за этого диагностический файл превращается в источник утечки секретов.

JEP 536 решает эту проблему на уровне JVM: секреты редактируются до того, как данные покидают процесс. Теперь JFR по умолчанию будет подставлять [REDACTED] вместо секретов.

Например, чтобы скрыть какие-то переменные окружения или свойства системы под названием confidential или CONFIDENTIAL, а также аргументы командной строки, которые выглядят как URL и содержат логин и пароль (ср. username:password@host), используйте опцию -`XX:FlightRecorderOptions` и укажите что вы хотите скрыть:

$ export CONFIDENTIAL=SOME_SECRET

$ java -XX:FlightRecorderOptions:'redact-key=confidential,redact-argument=https://*:*@*' \

       -XX:StartFlightRecording:filename=dump.jfr \

       -Dconfidential=ANOTHER_SECRET \

       -jar application.jar https://john:YET_ANOTHER_SECRET@example.com/login --verbose

В примере выше мы хотим, чтобы JFR скрыл значение переменной confidential (см. redact-key=) и аргумент командной строки https://*:*@* (см. redact-argument=) .

Чтобы удостовериться, что данные были скрыты, воспользуйтесь jfr print:

$ jfr print \

      --events InitialSystemProperty,JVMInformation,StringFlag,InitialEnvironmentVariable \

      dump.jfr

jdk.JVMInformation {

  startTime = 17:39:02.196 (2026-02-15)

  jvmVersion = "Java HotSpot(TM) 64-Bit Server VM"

  jvmArguments = "-Dconfidential=[REDACTED]

   -XX:FlightRecorderOptions:redact-key=confidential,redact-argument=[REDACTED]

   -XX:StartFlightRecording:filename=dump.jfr"

  jvmFlags = "N/A"

  javaArguments = "-jar application.jar [REDACTED] --verbose"

  jvmStartTime = 17:39:02.050 (2026-02-15)

  pid = 43671

}

jdk.InitialSystemProperty {

  startTime = 17:39:02.196 (2026-02-15)

  key = "confidential"

  value = "[REDACTED]"

}

jdk.InitialSystemProperty {

  startTime = 17:39:02.196 (2026-02-15)

  key = "sun.java.command"

  value = "-jar application.jar [REDACTED] --verbose"

}

jdk.StringFlag {

  startTime = 17:39:02.196 (2026-02-15)

  name = "FlightRecorderOptions"

  value = "redact-key=confidential,redact-argument=[REDACTED]"

  origin = "Command line"

}

jdk.InitialEnvironmentVariable {

  startTime = 17:39:02.244 (2026-02-15)

  key = "CONFIDENTIAL"

  value = "[REDACTED]"

}

По умолчанию JFR будет искать ключи (`redact-key`) по шаблонам вроде:

*api*key*
*auth*
*client*secret*
*credential*
*jaas*config*
*jwt*
*passphrase*
*passwd*
*password*
*private*key*
*pwd*
*secret*
*token*

А аргументы командной строки (`redact-argument`) по таким:

-*api*key *
-*client*secret *
-*credential *
-*jaas*config *
-*jwt *
-*passphrase *
-*passwd *
-*password *
-*private*key *
-*pwd *
-*secret *
-*token *
*api*key*
*client*secret*
*credential*
*jaas*config*
*passphrase*
*passwd*
*password*
*private*key*
*pwd*
*secret*
*token*

Типичные случаи закроются без дополнительной настройки.

Если вы укажете свои redact-key и/или redact-argument, то фильтры по умолчанию не сохранятся. Чтобы добавить собственные фильтры к фильтрам по умолчанию, используется префикс +:

$ java -XX:FlightRecorderOptions:'redact-key=+confidential;secret;@keys.txt' ...

Чтобы не “раздувать” командную строку, фильтры можно загрузить из файла:

java \

  '-XX:FlightRecorderOptions:redact-argument=@args.txt,redact-key=@keys.txt' \

  -XX:StartFlightRecording:filename=dump.jfr \

  -jar app.jar

Если вам по какой-то причине понадобится отключить фичу, то подставьте в  redact-argument и redact-key значение none:

$ java -XX:FlightRecorderOptions:'redact-argument=none,redact-key=none' ...

Помните, если ваше приложение пишет секреты в логи, кастомные JFR-события или в сообщения об исключениях, то JDK не сможет понять весь бизнес-контекст и скрыть все ваши секреты. Секреты не должны попадать в диагностические данные на уровне приложения.

Стандартная библиотека

Несколько приятных фичей в стандартной библиотеке Java.

JEP 531: Ленивые константы (третье превью)

В Java есть конфликт: final удобно и безопасно, потому что значение задаётся один раз, JVM может ему доверять, а код проще анализировать. Однако final требует ранней инициализации:

class OrderController {

    private final Logger logger = Logger.create(OrderController.class);

    void submitOrder(User user, List<Product> products) {

        logger.info("order started");

        ...

        logger.info("order submitted");

    }

}

Если создание Logger дорогое, то каждый OrderController платит эту цену сразу. Даже если логгер никогда не понадобится.

Раньше инициализацию таких объектов откладывали до последнего, чтобы они создавались только по необходимости. Один из способов — отказаться от final и довериться неизменяемым полям:

class OrderController {

    private Logger logger = null;

    Logger getLogger() {

        if (logger == null) {

            logger = Logger.create(OrderController.class);

        }

        return logger;

    }

    void submitOrder(User user, List<Product> products) {

        getLogger().info("order started");

        ...

        getLogger().info("order submitted");

    }

}

Благодаря ленивым константам (Lazy Constants) — API для отложенной инициализации неизменяемых значений, мы можем переписать пример выше следующим образом:

class OrderController {

    // Прежний вариант:

    // private Logger logger = null;

    // Новый вариант:

    private final LazyConstant<Logger> logger

        = LazyConstant.of(() -> Logger.create(OrderController.class));

    void submitOrder(User user, List<Product> products) {

        logger.get().info("order started");

        ...

        logger.get().info("order submitted");

    }

}

Что важно:

  • Значение вычисляется при первом обращении.

  • Вычисляется не больше одного раза.

  • Корректно работает при конкурентном доступе.

  • После инициализации считается неизменяемым.

  • JVM может оптимизировать доступ ближе к final-семантике.

В JDK 27 (JEP 531) изменили следующее:

  • Убрали низкоуровневые методы isInitialized и orElse, чтобы сделать API проще и снизить риск его неправильного использования.

  • Добавить новый factory-метод Set.ofLazy(...), который позволяет задать фиксированный набор возможных элементов, но вычислять вхождение каждого конкретного элемента в итоговое множество только в момент проверки. Благодаря этому у всех трёх базовых типов коллекций появятся “ленивые” версии: List, Set и Map.

Это API находится в превью. Чтобы воспользоваться фичей, явно включите её.

JEP 533: Структурная многопоточность (седьмое превью)

Структурная многопоточность (Structured Concurrency) призвана упростить работу с конкурентным кодом в Java.

Идея в том, чтобы рассматривать несколько связанных задач как одну единицу работы: они запускаются вместе, завершаются вместе, а ошибки обрабатываются более предсказуемо. Каждая подзадача запускается в отдельном потоке через fork, а затем все они ожидаются вместе через join. Это полезно в ситуациях, когда в рамках одного запроса нужно параллельно получить несколько данных, например, загрузить пользователя, его заказы и рекомендации.

В однопоточном варианте handle() связь между задачей и подзадачами видна прямо из структуры кода:

Response handle() throws IOException {

    String theUser = findUser();

    int theOrder = fetchOrder();

    return new Response(theUser, theOrder);

}

Здесь fetchOrder() не запускается, пока не завершится findUser(). Если findUser() падает с ошибкой, fetchOrder() вообще не выполняется, а handle() завершается неуспешно.

В однопоточном коде такая иерархия естественно отражается в стеке вызовов: findUser(), а затем fetchOrder() являются подзадачами handle().

С конкурентным кодом было бы проще работать, если бы отношения между родительской задачей и её подзадачами так же явно следовали из структуры кода и сохранялись во время выполнения.

В Java уже есть ForkJoinPool, который задаёт структуру для параллельных задач. Однако он ориентирован прежде всего на вычислительные задачи, а не на I/O-сценарии.

Вот как можно переписать пример выше с использованием структурной многопоточности:

Response handle() throws ExecutionException, InterruptedException {

    try (var scope = StructuredTaskScope.open()) {

        Subtask<String> user = scope.fork(() -> findUser());

        Subtask<Integer> order = scope.fork(() -> fetchOrder());

        scope.join();   // Соединяем подзадачи, propagating exceptions

        // Обе подзадачи завершились успешно, so compose their results

        return new Response(user.get(), order.get());

    }

}

StructuredTaskScope ограничивает время жизни подзадач лексической областью — блоком try-with-resources, внутри которого происходят запуск, ожидание, обработка ошибок и сбор результатов.

В отличие от варианта с ExecutorService, здесь жизненный цикл потоков понятен: при любом исходе он ограничен телом try-with-resources.

StructuredTaskScope даёт несколько важных свойств:

  • Если findUser() или fetchOrder() завершается с исключением, вторая подзадача отменяется, если ещё не успела завершиться.

  • Если поток, выполняющий handle(), прервали до или во время join(), обе подзадачи будут автоматически отменены при выходе из scope.

  • Код явно показывает этапы — запустить подзадачи, дождаться завершения или отмены, затем собрать результат или завершиться с ошибкой.

  • Структурная многопоточность хорошо ложится на виртуальные потоки (virtual threads). Виртуальные потоки дают много “дешёвых” потоков, а структурная многопоточность помогает ими правильно управлять.

Структурная многопоточность впервые появилась в JDK 19 (JEP 428), а затем в JDK 20 (JEP 437). В JDK 21 (JEP 453) API перешло в статус превью, при этом метод fork изменили: он стал возвращать Subtask, а не Future. В таком виде API снова выходило в превью в JDK 22 (JEP 462), JDK 23 (JEP 480) и JDK 24 (JEP 499).

Затем структурная многопоточность снова была вынесена на превью в JDK 25 (JEP 505), уже с несколькими изменениями API. Самое заметное из них — публичные конструкторы StructuredTaskScope заменили статическими фабричными методами. В JDK 26 (JEP 525) API снова вышло в превью с несколькими небольшими изменениями.

В JDK 27 предлагается ещё один превью этого API со следующими изменениями:

  • Интерфейсы StructuredTaskScope и Joiner теперь имеют третий параметр типа — R_X, который задаёт тип исключения, выбрасываемого методом join() у StructuredTaskScope.

  • В StructuredTaskScope добавлен новый статический метод open, который реализует политику объединения задач по умолчанию и использует переданный UnaryOperator для формирования конфигурации StructuredTaskScope.

  • Фабричные методы JoinerallSuccessfulOrThrow(), anySuccessfulOrThrow() и awaitAllSuccessfulOrThrow() — теперь создают joiner’ы, из-за которых join() выбрасывает ExecutionException, если результатом выполнения стало исключение. Новые перегрузки этих трёх методов позволяют передать Function, которая создаёт другое исключение.

  • Фабричный метод Joiner.awaitAll() удалён.

  • Метод onTimeout() интерфейса Joiner заменён методом timeout(). Новый метод либо возвращает результат, либо выбрасывает исключение, если scope был отменён из-за таймаута. Если timeout() выбрасывает исключение, оно выбрасывается с CancelledByTimeoutException в качестве причины.

JEP 537: Векторное API (двенадцатый инкубатор)

Векторное API появилось в JDK 16 (JEP 388) в модуле jdk.incubator.vector и остаётся в инкубационном периоде. В JEP 537 API переходит без изменений. Только встроенную библиотеку SLEEF, которая используется для векторных математических интринсик на ARM и RISC-V, обновили с версии 3.6.1 до 3.9.0.

Векторное API нужно для векторных вычислений, которые во время выполнения компилируются в оптимальные SIMD-инструкции на конкретной платформе.

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

Векторное API останется в инкубаторе тех пор, пока необходимые возможности Project Valhalla не будут доступны в превью. Как только это произойдет, векторное API перейдёт из инкубатора в статус превью.

Нам обещают, что JEP 401: Value Objects (Preview) в паре с JEP 539: Strict Field Initialization in the JVM (Preview) уже войдут в JDK 28. Так что скоро будем активно обсуждать уже их.

JEP 532: Примитивные типы в паттернах, instanceof и switch (пятое превью)

Примитивные типы в паттернах, instanceof и switch были представлены в JDK 23 (JEP 455) в превью, остались в превью без изменений в JDK 24 (JEP 488), JDK 25 (JEP 507) и JDK 26 (JEP 530). В JDK 27 (JEP 532) предлагается в пятый раз выпустить фичу в превью без изменений.

Долгое время паттерны в основном работали со ссылочными типами. Теперь же с примитивными типами можно работать в паттернах, instanceof и switch.

Это делает проверки чисел и преобразования типов более выразительными и безопасными.

Это API находится в превью. Чтобы воспользоваться фичей, явно включите её.

Выводы

Java 27 — не LTS-релиз, но это не значит, что его нужно пропускать. Есть возможность заранее проверить новые API, оценить совместимость библиотек и инструментов и понять, какие изменения могут войти в будущие рабочие версии платформы. В Java-платформе последовательно дорабатывается фундамент: управление памятью, диагностика, криптография и стандартные API.

Кроме того, недавно вышел месячный CSPU-релиз, в том числе и для не-LTS Java 26. С новым релизным циклом Java теперь важно планировать не только обновление до GA-версии, но и до таких промежуточных релизов.

Для экосистемы начинается новый день: без резкого перезапуска, но с заметными изменениями внутри.

View the original on Хабр

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.