
Всем привет! 👋 👋 👋 👋 👋 Мы Java-разработчики Т-Банка: Андрей, Арсений, Константин, Константин и Роман. Собираем интересные новости, статьи, туториалы и другие материалы из мира Java-разработки и делимся этим со всем сообществом.
Сегодня вышла Java 24! Давайте посмотрим, что нового она принесла нам!
Завершенные JEP
JEP 483: Ahead-of-Time Class Loading & Linking — первый JEP проекта Leyden ⚡⚡⚡ Теперь в Java есть AOT из коробки. Пока это касается только подгрузки классов, их связывания за счет тренировочного запуска приложения и сохранения полученной информации в специальном кэше. Но это уже может в разы ускорить запуск программ.
Видео на эту тему: A Preview of What's Coming in Project Leyden - Inside Java Newscast #78

____________________________________________________________________
JEP 485: Stream Gatherers — одно из самых интересных нововведений в стандартной библиотеке. Теперь в Stream API есть возможность определять кастомные промежуточные операции — накопители (gather). По сути, это промежуточный аналог сборщиков, выглядит вот так:
Stream.of(1,2,3,4,5,6,7,8,9).gather(new WindowFixed(3)).toList()
В примере накопитель WindowFixed
нарезает исходный список элементов на списки по три элемента. Результат: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
В стандартной библиотеке уже определено несколько накопителей в классе Gatherers. Чтобы реализовать свой накопитель, нужно имплементировать интерфейс java.util.stream.Gatherer.
Видео на эту тему:
Better Java Streams with Gatherers - JEP Cafe #23
Better Java Streams with Gatherers - Inside Java Newscast #57
____________________________________________________________________
JEP 493: Linking Run-Time Images without JMODs может уменьшить размер JDK примерно на 25% за счет расширения возможностей инструмента jlink. Теперь jlink может создавать пользовательские исполняемые образы без использования JMOD-файлов, извлекая необходимые классы, библиотеки и ресурсы из существующего исполняемого образа JDK. Эта функция активируется во время сборки JDK и не включена по умолчанию, поэтому некоторые поставщики JDK могут решить ее не использовать.
____________________________________________________________________
JEP 472: Prepare to Restrict the Use of JNI — «Подготовка к ограничению использования JNI», направлен на повышение безопасности Java-приложений путем ограничения взаимодействия с нативным кодом.
В JDK 24 при загрузке нативных библиотек через методы System::load
и System::loadLibrary
, а также при вызове native
-методов будут выводиться предупреждения, если не включен специальный доступ к нативному коду. Это подготовит разработчиков к будущим версиям JDK, где такие операции будут запрещены по умолчанию для обеспечения целостности платформы.
Рекомендуется явно разрешать доступ к нативному коду с помощью опции командной строки --enable-native-access,
чтобы избежать предупреждений и обеспечить совместимость.

____________________________________________________________________
JEP 491: Synchronize Virtual Threads without Pinning оптимизирует работу виртуальных потоков, использующих synchronized
-методы и блоки. Он позволяет виртуальным потокам, блокирующимся в критических секциях, освобождать свои нативные потоки ОС для использования другими виртуальными потоками.
Джеп устраняет почти все случаи привязки виртуальных потоков к платформенным потокам, что раньше ограничивало количество виртуальных потоков, доступных для обработки рабочей нагрузки.
Раньше, если виртуальный поток выполнял synchronized
-метод и блокировался, он оставался привязанным к своему платформенному потоку, что снижало общую производительность. Теперь виртуальные потоки могут освобождать свои платформенные потоки даже внутри synchronized
-блоков, улучшая эффективность и масштабируемость многопоточных приложений.

JEP 475: Late Barrier Expansion for G1 дает перевести «разворачивание» GC-барьеров для сборщика мусора G1, то есть при разборе байт-кода в C2-фазе, на стадии после C2. Иными словами, вместо того чтобы раздувать код барьеров заранее и тем самым тормозить компиляцию фазы C2 на 10—20%, теперь все происходит в последний момент. Подход проверен временем в ZGC.

____________________________________________________________________
JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism вводит в Java квантово-устойчивый механизм передачи симметричных ключей ML-KEM, основанный на решеточной криптографии. Метод защищает данные от атак квантовых компьютеров, что с учетом развития квантовых вычислений обеспечит безопасную передачу ключей и на долгое время повысит безопасность Java-приложений.
JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm похож на предыдущий. Но если JEP-496 обеспечивал квантовую устойчивость для симметричных ключей, то JEP-497 обеспечивает квантово-устойчивый механизм для создания и проверки цифровых подписей по алгоритму ML-DSA
Видео про JEP 496 и JEP 497: Java Resists Quantum Attacks - Inside Java Newscast #85

____________________________________________________________________
JEP 484: Class-File API вводит официальный API для работы с class-файлами, заменяя библиотеки, такие как ASM или Javassist, который привязан к конкретным версиям байт-кода. Сейчас это создает проблему: при обновлении Java нужно обновлять Spring, Hibernate, Lombok и другие фреймворки, использующие ASM, иначе они ломаются из-за несовместимости формата class-файлов. Новый API должен решить проблему, поскольку позволит анализировать и генерировать байт-код без зависимости от сторонних библиотек и упростить миграцию на новые версии JDK.
Видео на эту тему: New Class-File API will make Java Updates easier - Inside Java Newscast #56

____________________________________________________________________
JEP 486: Permanently Disable the Security Manager. Завершает путь Security Manager, который уже давно утратил популярность и стал источником лишней сложности в кодовой базе JDK. Начиная с JDK 24 возможность включения Security Manager будет полностью удалена — его нельзя будет включить ни командной строкой, ни программно, через System.setSecurityManager().
Изменение позволит избавиться от тысяч проверок разрешений и освободить ресурсы для внедрения новых, более актуальных механизмов безопасности, таких как современные криптографические протоколы и улучшенные средства защиты от злонамеренных данных.
____________________________________________________________________
JEP 498: Warn upon Use of Memory-Access Methods in sun.misc.Unsafe. В этом JEP разработчики решили окончательно предупредить пользователей о том, что методы доступа к памяти в классе sun.misc.Unsafe устарели и скоро будут удалены. Начиная с JDK 23 они объявлены устаревшими, а в JDK 24 при первом их использовании по умолчанию будет выдаваться предупреждение. Современные и безопасные альтернативы, такие как VarHandle API (JDK 9) и Foreign Function & Memory API (JDK 22), уже давно готовы заменить эти опасные методы.
Preview & Experimental JEP
JEP 499: Structured Concurrency (4 Preview) — «Структурированная конкурентность», представляет API для упрощения многопоточного программирования в Java. Структурированная конкурентность рассматривает как единое целое группы связанных задач, выполняющихся в разных потоках. Такой подход упрощает обработку ошибок и отмену задач, повышает надежность и улучшает наблюдаемость.
Структурированная конкурентность помогает избежать утечек потоков и задержек при отмене задач, делая код более читаемым и поддерживаемым. API был впервые представлен в JDK 19 и с тех пор прошел несколько итераций, чтобы собрать обратную связь от сообщества и улучшить его перед окончательным включением в стандартную библиотеку.
Пример использования:
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
var task1 = scope.fork(() -> performTask("first task"));
var task2 = scope.fork(() -> performTask("second task"));
scope.join();
scope.throwIfFailed();
log.info("first task result 1: {}", task1.get());
log.info("second task result 2: {}", task2.get());
} catch (ExecutionException | InterruptedException e) {
log.error("Execution exception, e.getMessage());
}
____________________________________________________________________
JEP 488: Primitive Types in Patterns, instanceof, and switch (Second Preview) направлен на дальнейшее развитие паттерн-матчинга в Java. Он даст нам еще больше интересных инструментов для написания лаконичного и выразительного кода. Например, станет возможно писать вот такие конструкции:
float v = ...
switch (v) {
case 0f -> 5f;
case float x when x == 1f -> 6f + x;
case float x -> 7f + x;
}
if (i instanceof byte b) {
... b ...
}
Видео на эту тему:
Java 23: Restoring the Balance with Primitive Patterns - Inside Java Newscast #66
Pattern Matching in Java - Past, Present, Future
____________________________________________________________________
JEP 494: Module Import Declarations (Second Preview) призван навести порядок в импортах. Он позволяет одной короткой строчкой импортировать все пакеты, предоставляемые конкретным модулем. И да, эту фичу можно применять, даже если в вашем проекте модули не используются. Теперь вместо
import javax.xml.*;
import javax.xml.parsers.*;
import javax.xml.stream.*;
можно будет написать: import module java.xml;

Константин
Думаю, наибольший профит эта фича принесет для решения конфликтов в git. Будем честны, в 99 из 100 случаев мы вспоминаем про импорты, именно когда решаем конфликты 🙂
Видео на эту тему: Module Imports in Java 23 - Inside Java Newscast #69
____________________________________________________________________
JEP 495: Simple Source Files and Instance Main Methods(Fourth Preview). Основная цель этого JEP — снижение порога входа для новых разработчиков. Профессионалы смогут быстрее и лаконичнее писать какие-то простые скрипты. А новички могут начинать с более простых концепций и лишь по мере погружения использовать что-то более сложное. Условный Hello World станет таким:
void main() {
println("Hello, World!");
}
Видео на эту тему:
Does Java 22 Kill Build Tools? - Inside Java Newscast #63
Script Java Easily in 21 and Beyond - Inside Java Newscast #49

____________________________________________________________________
JEP 404: Generational Shenandoah (Experimental) добавляет поддержку generational сборки мусора в Shenandoah GC, разделяя кучу на молодое и старое поколения. Идея такая же, как в Generational ZGC, официально вышедшем в JDK 21.
Сама идея разделения на поколения позволяет снизить время пауз сборки мусора, улучшает управление памятью и повышает производительность JVM, поскольку молодые объекты удаляются быстрее, а старые обрабатываются реже.
В Java 24 Generational Shenandoah доступен в качестве экспериментальной фичи и включается при помощи флагов -XX:+UnlockExperimentalVMOptions и -XX:ShenandoahGCMode=generational
____________________________________________________________________
JEP 450: Compact Object Headers (Experimental) — часть Project Liliput, он призван уменьшить размер заголовков объектов в памяти JVM на 64-разрядных архитектурах, снижая накладные расходы и улучшая эффективность работы с кучей. Это особенно полезно для приложений с большим количеством мелких объектов, так как позволит уменьшить общий объем используемой памяти и ускорить работу GC.
Видео про JEP 450: Save 10-20% Memory With Compact Headers - Inside Java Newscast #48
Доклад Романа Кеннке о Project Liliput в целом и его дальнейших планах: Project Lilliput - Beyond Compact Headers #JVMLS
_______________________________________________________
JEP 487: Scoped Values (4 Preview). Scoped Values несут неизменяемые данные для вызываемых объектов внутри потоков и для дочерних потоков. В этой итерации из класса ScopedValue были удалены методы callWhere и runWhere, эти методы отправились в ScopedValue.Carrier.call и ScopedValue.Carrier.run соответственно.
ScopedValue очень похожи на ThreadLocal-переменные, но у ScopedValue более простой API, и они эффективнее передаются между большим количеством потоков, особенно виртуальных. Стоит отметить, что у этой доработки нет цели заменить ThreadLocal.
Видео на эту тему: Scoped Values in Java 24 - Inside Java Newscast #86

_______________________________________________________
JEP 492: Flexible Constructor Bodies (3 Preview) должен позволить объявление вызова super или this в любом месте конструктора. Такое объявление даст возможность обрабатывать входные параметры конструктора перед инициализацией переменных класса или ранний выход из инициализации:
public class PositiveBigInteger extends BigInteger {
public PositiveBigInteger(long value) {
super(value); // Potentially unnecessary work
if (value <= 0) throw new IllegalArgumentException(..);
}
}
Как можно сделать валидацию до инициализации сейчас:
public class PositiveBigInteger extends BigInteger {
private static long verifyPositive(long value) {
if (value <= 0) throw new IllegalArgumentException(..);
return value;
}
public PositiveBigInteger(long value) {
super(verifyPositive(value));
}
}
Как будет можно после JEP:
public class PositiveBigInteger extends BigInteger {
public PositiveBigInteger(long value) {
if (value <= 0) throw new IllegalArgumentException(..);
super(value);
}
}
Последняя конструкция выглядит более естественно. В самом JEP еще множество примеров, как это можно использовать. Думаю, и ты, дорогой читатель, придумаешь их немало.
Видео на эту тему: Java 22 Previews Statements Before super(...)
and this(...)
- Inside Java Newscast #62
_______________________________________________________
JEP 478: Key Derivation Function API (Preview) — это предварительный API для реализации криптографических функций вывода ключей. Новый API позволяет применять современные алгоритмы, такие как HKDF (на базе HMAC) и в будущем Argon2, что дает разработчикам возможность создавать криптографически надежные ключи из исходного секрета и дополнительных данных.
Новый API особенно актуален в условиях, когда с каждым днем усиливается внимание к квантовой безопасности и постквантовой криптографии. API спроектирован так, чтобы его можно было легко расширять: разработчики смогут реализовывать свои алгоритмы вывода ключей как на чистом Java, так и на нативном коде.
Среди основных возможностей — два метода для генерации ключей: один возвращает объект SecretKey по указанному алгоритму, а другой — массив байтов для дальнейшего использования. При этом API оставляет прежние реализации PBKDF1 и PBKDF2 в стороне, сосредоточив внимание на более современных и гибких алгоритмах.
Инкубатор
JEP 489: Vector API (Ninth Incubator) — Vector API продолжает оставаться в инкубаторе до тех пор, пока необходимые фичи проекта Valhalla не выйдут в Preview.

Феня
Мур! Да, эта фича еще ждет своего часа. Но будьте уверены, что со мной она засияет ярче Бивреста! Ведь ее цель — дать вашим программам значительное ускорение вычислений за счет SIMD прямо из коробки. Для этого нужен новый подход к работе с объектами в памяти, который я и привнесу в Java.
Видео на эту тему: Learn how to write fast Java code with the Vector API - JEP Café #18
Устаревшие и удаленные

JEP 490: ZGC: Remove the Non-Generational Mode. Non-Generational-режим в ZGC — все! В JDK 24 даже при включении этого режима будет включен generational и будет выдан WARN.
JEP 479: Remove the Windows 32-bit x86 Port удаляет 32-битный порт для Windows, который был уже помечен на удаление в JDK 21.
JEP 501: Deprecate the 32-bit x86 Port for Removal. Помечен на удаление последний 32-битный порт в JDK, удалить его собираются уже в следующем релизе.
Спасибо, что читаете! Залетайте в комментарии, если хотите что-то обсудить или добавить 😉