Реліз Java 19: 7 нових JEP та ще багато покращень

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Цей день настав! Офіційний реліз JDK 19 вже сьогодні, вже зараз. А це значить, що треба розібратися, що ж в ньому нового.

Java 19 General-Availability

Реліз JDK 19 є десятим за рахунком Feature Release, який було своєчасно випущено в рамках шестимісячної каденції. Такий рівень передбачуваності дозволяє розробникам досягати відносно простого, послідовного та не витратного за часом впровадження інновацій завдяки постійному потоку очікуваних змін.

Ще однією важливою зміною під час релізу Oracle JDK 17 стало введення нових і простіших ліцензійних умов, які дозволять компаніям використовувати Oracle JDK 17, включаючи щоквартальні патчі продуктивності, стабільності та безпеки, безкоштовно протягом щонайменше наступних трьох років, дозволяючи один повний рік перекриття з наступним LTS випуском.

Передплатники Java SE отримують доступ до підтримки Java SE від Oracle та комерційних функцій, таких як GraalVM Enterprise, Java Management Service і Advanced Management Console. Детальніше про нові ліцензійні умови Java SE доступно тут.

Вклад компаній у Java 19

З 19 297 тікетів у JIRA, позначених як виправлені у релізах Java 11-Java 19 на момент їх General-Availability, 13 825 були завершені людьми, що працюють в Oracle, тоді як 5 472 були внесені індивідуальними розробниками та розробниками, що працюють в інших організаціях:

У Java 19 з 1 962 тікетів у JIRA, позначених як виправлені, 1 383 були завершені Oracle, а 579 були внесені іншими членами спільноти Java.

Що нового у Java 19

JDK Enhancement Papers

Отже, почнемо із глобальних змін, які несуть нові JDK Enhancement Papers (JEP):

  • JEP 405 Record Patterns (Preview)
  • JEP 422 Linux/RISC-V Port
  • JEP 424 Foreign Function & Memory API (Preview)
  • JEP 425 Virtual Threads (Preview)
  • JEP 426 Vector API (Fourth Incubator)
  • JEP 427 Pattern Matching for switch (Third Preview)
  • JEP 428 Structured Concurrency (Incubator)

Нововведення у JDK 19 (по за контекстом JEP):

Повний перелік нововведень доступний у Release Notes. Найцікавіше (нові JEP) ми все ж таки розглянемо.

Project Loom

JEP 425: Virtual Threads

З’явився новий тип Java-потоків — Virtual Thread. На відміну від класичних потоків, віртуальні вже не мають прямого співвідношення до системних потоків. А також їхня кількість більше не залежить від кількості доступних системних потоків, а лише від наявної пам’яті, якою оперує JVM. Новий функціонал буде доступний у форматі preview feature. Конструкції, з якими доведеться мати справу:

Thread.startVirtual(
        () -> System.out.println(Thread.currentThread())
    );

та

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    executor.submit(() -> {
        Thread.sleep(Duration.ofSeconds(1));
    });
}

Деталізований розбір доступний тут.

JEP 428: Structured Concurrency

Structured Concurrency вже на стадії інкубатора, новий функціонал спрощує багатопотокове програмування за допомогою структурованого паралелізму. Цей паралелізм розглядає декілька завдань, що виконуються в різних потоках, як єдину робочу одиницю, щоб спростити обробку та скасування помилок:

static Callable<Integer> task = () -> {
    System.out.println(Thread.currentThread());
    Thread.sleep(Duration.ofSeconds(1));
    return 42;
};
static void simpleScope() throws InterruptedException {
    try(var scope = new StructuredTaskScope<>()) {
        var fut = scope.fork(task);
        scope.join();
        System.out.println(fut.resultNow());
    }
}

Деталізований розбір доступний тут, тут, тут і тут.

Project Amber

JEP 405: Record pattern matching

Загалом, patter matching використовується для двох задач: встановлення типу, та приведення змінної до певного типу, якщо змінна такою є, наприклад:

Object object = ...; // any object
if (object instanceof String s) {
    int length = s.length();
    System.out.println("This object is a string of length" + length);
} else {
    System.out.println("This object is not a string.");
}

Що ж стосується рекордів, то тут ситуація може бути наступною:

record Point(int x, int y) {}
var p = (Object) new Point(1, 2);
if (pObject instanceof Point newP) {
System.out.println(newP);
}

Тобто, працює той самий механізм як і раніше, але тепер є можливість організувати більш гранулярний доступ до атрибутів рекорду:

record Point(int x, int y) {}
var p = (Object) new Point(1, 2);
if (pObject instanceof Point(int x, int y)) {
System.out.printf(“Point[x=%d, y=%d]\n”, x, y);
}

Повний та детальний опис функціонала доступний у JEP 405.

JEP 427: Patter matching for switch

У Java 16, JEP 394 розширив оператор instanceof для використання у межах pattern matching. Це скромне розширення дозволяє спростити знайому ідіому instanceof та cast:

if (o instanceof String s) {
    ...
}

Ми часто бажаємо порівнювати змінну з декількома альтернативами. Java підтримує багатосторонні порівняння з допомогою операторів switch і, починаючи з Java 14, switch expression (JEP 361). Отже, набір гілок if-esle можна переробити на наступну структуру:

static void testFooBar(String s) {
    switch (s) {
        case null         -> System.out.println("Oops");
        case "Foo", "Bar" -> System.out.println("Great");
        default           -> System.out.println("Ok");
    }
}

Частіше за все є необхідність визначитися із типом змінної та ії контетом одночасно, тому доводиться робити наступні конструкції:

class Shape {}
class Rectangle extends Shape {}
class Triangle  extends Shape { int calculateArea() { ... } }

static void testTriangle(Shape s) {
    switch (s) {
        case null:
            break;
        case Triangle t:
            if (t.calculateArea() > 100) {
                System.out.println("Large triangle");
                break;
            }
        default:
            System.out.println("A shape, possibly a small triangle");
    }
}

Проблема тут полягає в тому, що використання одного шаблону для розрізнення кейсів не виходить за рамки однієї умови — нам потрібен якийсь спосіб виразити уточнення шаблону. Один з підходів полягає у введенні guarded patterns, які дозволяють уточнити шаблон за допомогою довільного булевого визару:

static void testTriangle(Shape s) {
    switch (s) {
        case null -> 
            { break; }
        case Triangle t when t.calculateArea() > 100 ->
            System.out.println("Large triangle");
        default ->
            System.out.println("A shape, possibly a small triangle");
    }
}

Отже, конструкція case ... when ... -> ... дозволяє формувати більш складні кейси із використанням patter matching.

Більше матеріалів по Project Amber можна знайти тут і тут.

Project Panama

JEP 424: Foreign Function & Memory API

Нарешті, повноцінна заміна JNI, яка реалізує Application Binary Interface і дозволяє використовувати C ABI, для роботи з нативними С бібліотеками напряму та через extern C з С++ бібліотеками. Якщо хочете розібратися у цій темі, я дуже рекомендую прочитати мій цикл статей тут на DOU:

Зверніть увагу, що функціонал доступний у форматі preview feature. Щоб працювати з цим API, треба:

  • Скомпілюйте програму за допомогою javac --release 19 --enable-preview Main.java та запустіть її за допомогою java --enable-preview Main.
  • Використовуючи програму запуску вихідного коду, запустіть програму з java --source 19 --enable-preview Main.java.
  • Використовуючи jshell, почніть його з jshell --enable-preview.
  • Додайте відповідний модуль --add-modules jdk.incubator.vector --enable-native-access=ALL-UNNAMED

JEP 426: Vectors API

Функціонал, який поставляється у рамках OpenJDK Project Panama не обмежений лише набором класів для експлуатації C ABI у рамках JVM та новим інструментом кодогенерації — jextract. Дуже важливими нововведеннями для розробників є так звані Vectors API — набір класів, суть котрих полягає в наданні певних можливостей для реалізації векторної алгебри (криптографія, мультимедіа, AI/ML). Отже, ця стаття спрямована на те, щоб на певних прикладах показати, що таке Vectors API, звідки воно походить, та як їх використовувати у Java додатках.

Удосконалення API, запропоновані для JDK 19, включають поліпшення завантаження та зберігання векторів з MemorySegments, як визначено в попередньому перегляді Foreign Function and Memory API. JDK 19 також додасть дві перехресні векторні операції, стиснення та розширення, разом з додатковою операцією стиснення векторних масок. Операція стиснення корисна для фільтрації результатів обробки векторів.

Це вже 4-й інкубаторний реліз, який працює на всіх доступних архітектурах процесорів Intel, AMD, ARM. Вже є підтримка нових топових інструкцій типу AVX 512bit і ще багато цікавого. Від себе додам, що стаття про векторні обчислення вже написана та чекає публікації, а поки що можу поділитися результатами бенчмарку роботи AVX 128 біт (спільний знаменник між усіма архітектурами):

  • Vectors API;

  • Streams;

  • цикл for;

RISC-V

Метою проєкту є створення повнофункціонального переносу OpenJDK на платформу Linux/RISC-V, який може бути інтегрований в основну гілку розробки OpenJDK. Наразі планується підтримка порту JDK 19 на Linux на RISC-V. Вже є успішні спроби повноцінно портувати JDK та JVM на RISC-V, цей порт успішно пройшов тести JTREG, що вже означає, що більшість Java застосунків будуть працювати на цій архітектурі без проблем.

Сам проєкт створення порту JVM містить підлаштування C1, C2 JIT-компіляторів, найкращих GC типу ZGC.

Для довідки: RISC-V — це архітектура набору інструкцій з відкритим кодом та безоплатною ліцензією для обчислювальних платформ, починаючи від вбудованих систем, і закінчуючи корпоративними серверами. Наразі певні клаудпровайдери, типу Alibaba, вже пропонуються RISC-V для всіх бажаючих. Проєкт RISC-V просувають такі мастадонти як Google, nVIDIA, Samsung.

Дистрибутив JDK 19

Офіційні джерела

Офіційний реліз Oracle OpenJDK доступний тут — jdk.java.net/19

Офіційний реліз OracleJDK доступний тут — www.oracle.com/...​a/technologies/downloads

Офіційні Java action для GitHub

Реліз вже доступний для GitHub Actions:

steps:
  - name: 'Set up latest Oracle OpenJDK 19'
    uses: oracle-actions/[email protected]
    with:
      website: jdk.java.net
      release: 19

та

steps:
  - name: 'Set up latest Oracle JDK 19'
    uses: oracle-actions/[email protected]
    with:
      website: java.net
      release: 19

Офіційна документація

Oracle

Ліцензування

OracleJDK

Oracle OpenJDK

Трохи висновків

Java продовжує залишатися мовою програмування № 1 для сучасних технологічних тенденцій. Як показує своєчасне впровадження вдосконалень у Java 19, завдяки постійному ретельному плануванню та залученню екосистеми, платформа Java є добре позиціонованою для сучасного розвитку і зростання в хмарі.

Новий реліз хоч і не є Long-Time-Support версією, але несе дуже важливі зміни у JDK, особливо у два напрями:

  • багато-потоковість
  • авто-векторізація

Отже, цей реліз, та наступні будуть цікаві усім, хто розробляє мережеві додатки, проекти з досить складною математикою типу Tribuo, або інші AI/ML фрейморки, а також ті розробники хто захоче створити ті бібліотеки, яких ще не існує у Java екосистемі.

Слідкуйте за новинами та оновленнями за посиланням:

  • Dev.java (Спеціальний портал Oracle для поглиблення ваших знань з Java та участі у комʼюніті).
  • Inside.java (суто-технічний блог який ведуть архітектори та інженери що розроблюють Java).
  • Inside.java подксат про JDK, JVM, GC, core libs і так далі.
  • Inside.java Newscasts (щотижневе YouTube-шоу, суто про Java).
  • Java on YouTube (все про Java та екосистему).
  • OpenJDK mailing lists (місце, де можна дізнатися поточний стан речей у OpenJDK комʼюніті).
  • Підписуйтесь на OpenJDK and Java on Twitter.

----

Ну, і підписуйтесь на мене у Twitter. Там я роблю щотижневий #JavaTuesdayThread — про поглиблений функціонал JDK, про C/C++ у контексті Java та ще багато чого іншного.

Сподобалась стаття? Натискай «Подобається» внизу. Це допоможе автору виграти подарунок у програмі #ПишуНаDOU

👍ПодобаєтьсяСподобалось4
До обраногоВ обраному3
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Реліз йде відверто наступом на Python, усі підтачується під ML. Зараз якраз сам працюю над цим.

Вклад компаній у Java 19

поясніть на пальцях, чим цей графік корисний? виглядає як circle-jerk / реклама ентерпрайзів

Вона чітко й ясно показує фактичний вклад компаній у розвиток Java, а не створення власних дистрибутивів :wink:. Що він не показує, нажаль — персональні внески у Java від релізу до релізу. Але, якщо зовсім просто, то цей графік показує хто створю майбутне Java.

Передавайте мої вітання Метту Рейблу ;)

Запросто, ви персонально знайомі? Як вас представити?

Я колись виступав на DenverJUG підчас ковіду. Я думаю, що він зрозуміє.

О то це чувак який jhipster адвокейтив :)

Nice! That’s cool y’all got to meet. It’s nice to meet you too. Matt

Хто дівчину годує — той її і танцює. Не слід забувати, що левова доля цих компаній є патентними тролями, які зазвичай вичікують, доки якась технологія набере обертів та буде фактично інстальована на мільйонах та мільйардах пристроїв, а вже потім прокопаються до якогось коду у 10 строчок.

Хороший релиз. Жаль не LTS

Якщо ж бути відвертим, то ще не час для LTS, бо більша частина нового функціоналу або у preview, або incubated. Але в ж зазначу, що це найсштабніший реліз із початку нової концепції піврічних релізів.

Ще трохи і стане юзабельною.

А що саме вас не влаштовує наразі? Дуже цікаво, якщо честно.

Для минулого сторіччя досить непогано. Але немає null safety, thread safety, нормального которолю що mutable а що immutable. Є жор пам’яті.

так

null safety

нема адекватного у жодній мові програмування, але в Java є функціонал класу Objects типу docs.oracle.com/...​ts.html#requireNonNull(T

mutable а що immutable

взагалі є, наприклад у коллекціях (Set.of, List.of). Щодо обʼєктів, то є Java record — по-замовчанню іммутабільний обʼєкт. То що ще треба?

Є жор пам’яті

Вибачте мене, але без конкретики важко спростувати, чи підтримати вашу тезу.

нема адекватного у жодній мові програмування,

Rust, Kotlin (крім взаємодії з жабою), TypeScript (крім взаємодії з жабоскрiптом).

але в Java є функціонал класу Objects типу

Я ж і кажу що для минулого сторіччя досить непогано. Але хотілося б, щоб такого класу помилок взагалі не було.

То що ще треба?

Наприклад, імутабельність за умовчанням.

Для легасi мови норм.

Наприклад, імутабельність за умовчанням.

Навпаки, є простий спосіб зробити класс іммутабельним, а от зробити його мутабельним із іммутабельного призведе до породження багатьох екземплярів одного классу, та доведеться робити де-референсерінг дуже частно (те, що робить Kotlin, наприклад із своїми фінальними класами).

Я ж і кажу що для минулого сторіччя досить непогано. Але хотілося б, щоб такого класу помилок взагалі не було.

призведе до перевикористання памʼяті, бо NULL лише один, а замість нього доведеться створювати екземпляри класів для того, щоб уникнути NPE або явний перевірок на NULL у компанії із аннотаціями.

призведе до перевикористання памʼяті, бо NULL лише один, а замість нього доведеться створювати екземпляри класів

Нi. Мова йде про compile time первiрки. Наприклад в Rust Option<&T> займає в пам’ятi стільки скільки посилання на об’єкт. Оверхеду нема, comple time первiрки є.

Заждіть, але ж ви можете це зробити й зараз, але треба робити усе константами (static final), щоб C2 міг по-перше ії обчислити, й оптимізувати. Чи вам цього недостаньо?

Як static final захистить вiд NPE в методi doSomething(Foo bar) коли хтось зробить doSomething(null)?

немає null safety

www.jetbrains.com/...​-notnull-annotations.html
Так, в ніяке порівння з котліном не йде, але краще ніж нічого...

Підписатись на коментарі