Сучасна диджитал-освіта для дітей — безоплатне заняття в GoITeens ×
Mazda CX 30
×

Реліз Java 20: останній крок до великого релізу

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

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

Java 20 General-Availability

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

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

У Java 20 з 2314 проблем JIRA, позначених як виправлені, 1595 було завершено командою Oracle, а 719 було надано іншими членами спільноти Java. Компанія Oracle висловлює подяку розробникам, які працюють в таких організаціях, як Alibaba, Amazon, ARM, Google, Huawei, IBM, Intel, ISCAS, Red Hat, SAP і Tencent, за їх значний внесок. Ми також вдячні за внесок менших організацій, таких як Bellsoft та Loongson, а також незалежних розробників, які в сукупності внесли 7% виправлень у Java 20.

Що нового у Java 20

JDK Enhancement Papers

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

JEP 429

JEP 429 — API на стадії інкубатора дозволяє обмінюватися незмінними даними всередині потоків і між ними. Їм надається перевага перед локальними змінними потоку, особливо при використанні великої кількості віртуальних потоків. Значення з областю видимості дозволяє безпечно та ефективно обмінюватися даними між компонентами у великій програмі без використання аргументів методу. Цілі включають простоту використання, зрозумілість, надійність та продуктивність.

Розробники традиційно використовують локальні змінні потоку (thread locals), що з’явилися в Java 1.2, щоб допомогти компонентам застосунку обмінюватися даними, коли це саме потрібно. Локальна змінна потоку — це змінна типу ThreadLocal. Незважаючи на те, що вона виглядає як звичайна змінна, вона має декілька втілень, по одному для кожного потоку; конкретне втілення, яке використовується, залежить від того, який потік викликає її методи get() або set(...), щоб прочитати або записати її значення. Код в одному потоці автоматично читає і записує свій екземпляр, тоді як код в іншому потоці автоматично читає і записує свій власний окремий екземпляр. Зазвичай локальна змінна потоку оголошується як кінцеве статичне поле, щоб її можна було легко отримати з багатьох компонентів.

На жаль, локальні змінні потоку мають багато недоліків у дизайні, яких неможливо уникнути:

  • Необмежена змінюваність. Кожна локальна змінна потоку є змінюваною: будь-який код, який може викликати метод get() локальної змінної потоку, може викликати метод set(...) цієї змінної в будь-який час. ThreadLocal API дозволяє це, щоб підтримувати повністю загальну модель комунікації, де дані можуть передаватися у будь-якому напрямку між компонентами. Однак це може призвести до спагетіподібного потоку даних і до програм, в яких важко визначити, який компонент оновлює спільний стан і в якому порядку.
  • Необмежений час життя. Після того, як екземпляр локальної змінної потоку записано за допомогою методу set(...), цей екземпляр зберігається протягом усього часу життя потоку, або доки код у потоці не викличе метод remove(). На жаль, розробники часто забувають викликати remove(), тому внутрішньопотокові дані часто зберігаються довше, ніж потрібно. Крім того, у програмах, які покладаються на необмежену змінюваність локальних змінних потоку, може не бути чіткого моменту, коли потоку безпечно викликати remove(); це може призвести до довготривалого витоку пам’яті, оскільки дані потоку не буде очищено GC до завершення роботи потоку.
  • Дорога спадковість. Накладні витрати на локальні змінні потоку можуть бути гіршими при використанні великої кількості потоків, оскільки локальні змінні батьківського потоку можуть бути успадковані дочірніми потоками (локальна для потоку змінна насправді не є локальною для одного потоку). Коли розробник вирішує створити дочірній потік, який успадковує локальні для потоку змінні, дочірній потік має виділити пам’ять для кожної локальної для потоку змінної, попередньо записаної у батьківському потоці. Це може призвести до значного збільшення обсягу пам’яті. Дочірні потоки не можуть спільно використовувати пам’ять, яку використовує батьківський потік, оскільки локальні змінні потоку можуть змінюватися, а ThreadLocal API вимагає, щоб мутація в одному потоці не була видимою для інших потоків. Це прикро, оскільки на практиці дочірні потоки рідко викликають метод set(...) для успадкованих ними локальних змінних потоку.

Проблеми локальних змінних потоку стали ще більш актуальними з появою віртуальних потоків (JEP 425). Віртуальні потоки — це легкі потоки, реалізовані у JDK. Багато віртуальних потоків використовують один і той самий потік операційної системи, що дозволяє створювати дуже велику кількість віртуальних потоків. Крім того, що віртуальних потоків багато, вони ще й досить дешеві, щоб представляти будь-яку паралельну одиницю поведінки. Це означає, що вебфреймворк може призначити новий віртуальний потік для обробки запиту і при цьому мати можливість обробляти тисячі або мільйони запитів одночасно.

Таким чином, локальні змінні потоку мають більшу складність, ніж зазвичай потрібно для обміну даними, і значні витрати, яких неможливо уникнути. Платформа Java повинна надавати можливість підтримувати незмінні та успадковані потокові дані для тисяч або мільйонів віртуальних потоків. Оскільки ці потокові змінні будуть незмінними, їхні дані можуть ефективно використовуватися дочірніми потоками. Крім того, час життя цих поточних змінних має бути обмеженим: будь-які дані, до яких надається спільний доступ через потокову змінну, повинні ставати непридатними для використання після завершення роботи методу, який спочатку надавав спільний доступ до цих даних.

JEP 432

JEP 432 або Record Pattern у другому Preview розширюють мову програмування Java шаблонами для деконструкції значень записів. Record Pattern і шаблони типів можна вкладати один в одного, щоб забезпечити декларативну, потужну і комбіновану форму навігації та обробки даних. Цілі включають розширення можливостей зіставлення шаблонів для вираження складніших, комбінованих запитів до даних, не змінюючи при цьому синтаксис або семантику шаблонів типів. Основні зміни, порівняно з першою попередньою версією JDK 19, включають додавання підтримки виведення типів аргументів типових шаблонів записів, підтримку шаблонів записів, що відображаються у заголовку розширеного оператора for, та вилучення підтримки іменованих шаблонів записів. Отже, деконструкція типів дає змогу отримати доступ до складових record-классів через конструкцію patter matching:

static void printXCoordOfUpperLeftPointWithPatterns(Rectangle r) {
    if (r instanceof Rectangle(ColoredPoint(Point(var x, var y), var c),
                               var lr)) {
        System.out.println("Upper-left corner: " + x);
    }
}

А із JEP 432 впроваджується можливість використання паттернів усередині for-циклів:

record Point(int x, int y) {}

static void dump(Point[] pointArray) {
    for (Point(var x, var y) : pointArray) {
        System.out.println("(" + x + ", " + y + ")");
    }
}

JEP 434

Foreign Function & Memory API (FFM) об’єднує два попередні інкубаційні API: Foreign Function Memory Access API(JEP 370, 383 і 393) і Foreign Linker API (JEP 389). API FFM було інкубовано в JDK 17 за допомогою JEP 412, повторно інкубовано в JDK 18 за допомогою JEP 419, і вперше попередньо переглянуто в JDK 19 за допомогою JEP 424. У цьому JEP пропонується включити доопрацювання, засновані на відгуках, і повторно переглянути API у JDK 20. Ключові зміни відносно JDK 19:

  • уніфікація MemorySession & MemoryAddress для роботи із памʼяттю;
  • клас MemorySession розділено на Arena та SegmentScope, щоб полегшити спільне використання сегментів по всьому додатку.

Фактичною ж відмінністю є те, що Java наслідує концепцію арен памʼяті, яка була представлена у С++ як концептуальна ідея, в якій немає необхідності робити виділення памʼяті кожен раз за допомогою alloc/realloc/malloc. Концепція арени дозволяє одноразово виділити цілий сегмент памʼяті і позбутися його за одну операцію, що є суттєвим у порівнянні із виділенням памʼяті під змінні:

// 1. Find foreign function on the C library path
Linker linker          = Linker.nativeLinker();
SymbolLookup stdlib    = linker.defaultLookup();
MethodHandle radixsort = linker.downcallHandle(stdlib.find("radixsort"), ...);
// 2. Allocate on-heap memory to store four strings
String[] javaStrings = { "mouse", "cat", "dog", "car" };
// 3. Use try-with-resources to manage the lifetime of off-heap memory
try (Arena offHeap = Arena.openConfined()) {
    // 4. Allocate a region of off-heap memory to store four pointers
    MemorySegment pointers = offHeap.allocateArray(ValueLayout.ADDRESS, javaStrings.length);
    // 5. Copy the strings from on-heap to off-heap
    for (int i = 0; i < javaStrings.length; i++) {
        MemorySegment cString = offHeap.allocateUtf8String(javaStrings[i]);
        pointers.setAtIndex(ValueLayout.ADDRESS, i, cString);
    }
    // 6. Sort the off-heap data by calling the foreign function
    radixsort.invoke(pointers, javaStrings.length, MemorySegment.NULL, '\0');
    // 7. Copy the (reordered) strings from off-heap to on-heap
    for (int i = 0; i < javaStrings.length; i++) {
        MemorySegment cString = pointers.getAtIndex(ValueLayout.ADDRESS, i);
        javaStrings[i] = cString.getUtf8String(0);
    }
} // 8. All off-heap memory is deallocated here
assert Arrays.equals(javaStrings, new String[] {"car", "cat", "dog", "mouse"});  // true

Важливою зміною є впровадження SegmentScope API. Задача цього API — вказання рантайму відносно якої «арени» відбувається виділення памʼяті — або глобальної, або локальної арени, створенної через try-with-resource. Різниця полягає у тому, що глобальна «арена» буде зачищена лише під час завершення застосунку.

JEP 436 & JEP 437

Назначні зміни торкнулися віртуальних потоків, наразі йде стабілізація кодової бази та робота над новими API. Якщо цікаво дізнатися більше, то рекомендую почитати ось цей пост. Те ж саме стосується і StructuredConcurrency, детальний опис доступний ось тут.

JEP 433

Pattern matching for switch statements and expressions дозволяє стисло і безпечно виражати складні запити, орієнтовані на дані. Четверта Preview версія, яка вже була представлена у JDK 17, JDK 18 та JDK 19, дозволить продовжити еволюцію шаблонів записів, що сприятиме вдосконаленню на основі досвіду та зворотного зв’язку. Основні зміни у зіставленні шаблонів для перемикачів порівняно з третьою попередньою версією включають спрощену граматику для міток перемикачів і підтримку виведення типів аргументів для загальних шаблонів і шаблонів записів у операторах і виразах перемикачів.

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

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

Офіційний реліз Oracle OpenJDK доступний тут.

Офіційний реліз OracleJDK доступний тут.

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

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

steps:
  - name: 'Set up latest Oracle OpenJDK 19'
    uses: oracle-actions/setup-java@v1
    with:
      website: jdk.java.net
      release: 20

або

steps:
  - name: 'Set up latest Oracle JDK 19'
    uses: oracle-actions/setup-java@v1
    with:
      website: java.net
      release: 20

А також ми зробили Oracle JDK доступним через екшн від GitHub:

steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
  with:
    distribution: 'oracle'
    java-version: '20'
- run: java -cp java HelloWorldApp

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

Oracle

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

OracleJDK

Oracle OpenJDK

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

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

Новий реліз хоч і не є Long-Time-Support версією, але маленькими кроками наближає нас до кращого майбутнього із віртуальними потоками, нативним кодом та зручністю програмування.

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

  • 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 та ще багато чого іншного.

👍ПодобаєтьсяСподобалось6
До обраногоВ обраному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

Netty in action — почитати. Особливо багато з часів Брюса Ейкеля, з точки зору розробки не змінилось. Більше стрімів замість циклів, що іноді добре іноді ні. З’явились var, аналогічне C++ auto, record — дещо дуже схоже, на C — struct. Ніби усе, більшість змін в середені, які заділи Scala так само як і Java і Groovy і Kotlin і т.п. Якщо пишите на Play framework, або big data для Apache Spark — пишіть і далі на Scala. Під Spring — усе ще краще Java нічого нема. Android — пішов на Kotlin.

Взагалі незгодній із тим, щоб дивитися на Netty — це вже на стільки минуле сторіччя, що воно нікому для нових проектів не потрібно. Якщо справа саму у мережевому програмуванні, то я ДУЖЕ рекомендую дивитися на:
1. Helidon.
2. Quarkus
3. Spring Boot.

Взагалі, жодна книжка вам не допоможе так якісно як книжки по підготовці до сертифікації Java 17 (можна почати звідси www.google.pl/...​tilmEAAAQBAJ?hl=en&gbpv=0).
Далі треба розуміти що саме вам цікаво, якщо Spring — то шукати матеріали по Spring 6.
Щодо Java core — то можна просто подивитися перелік JEP-ів які були впроваджені, або пошукати матеріали по проектах OpenJDK типу Project Amber, Project Loom, Project Panama, Project Valhalla.
Як классика жанру, то можна почитати ось це www.manning.com/...​oks/modern-java-in-action.
Далі цікавою книжкою буде ось ця книжка мого колеги www.amazon.com/...​lai Parlog&s=books&sr=1-1

Ну і для фіналу — https://dev.java/, це наш комьюініті портал для вивчення Java, ми його дуже якісно ведемо і там є що почитати і чому повчитися.

Ще одне питання, є бажання погрузитися у Networking

Про те й річ. Netty is an NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients.

Helidon

Helidon is a cloud-native, open‑source set of Java libraries for writing microservices that run on a fast web core powered by Netty

Quarkus

quarkus.io/...​/io.quarkus/quarkus-netty

Spring Boot

www.baeldung.com/...​spring-boot-reactor-netty
Усі ці фреймворки високорівневі для створення мікросервісних застусунків.

Взагалі, жодна книжка вам не допоможе так якісно як книжки по підготовці до сертифікації Java 17

Звісно реклама вашого видання це добре, я скажімо дуже поважаю Тома Кайта, і разом з тим скажімо як може програма підготовки до сертифікації лише по мові, підготовити до скажімо доменної області ???

Про те й річ. Netty is an NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients.

Є певні обмеження у стандартній бібліотеці JDK, що не дає реалізувати певні сценарії, тому навіть netty nio вже не є релеватною технологією.

Helidon is a cloud-native, open‑source set of Java libraries for writing microservices that run on a fast web core powered by Netty

Вже ні, дивіться останні їх новини. Netty вже не використовується.

Звісно реклама вашого видання це добре

це не реклама, Oracle не видає такі матеріали від свого імені, якщо що.

як може програма підготовки до сертифікації лише по мові, підготовити до скажімо доменної області ?

людина ж задала питання відносно того, що нового в Java, а не у фремфорках, бо вони майже не змінилися з точки зору програмування.

Кажуть Java скоро стане такою самою лаконічною як котлін. Жидбрейнсам треба швидше викачувати мультиплатформу у stable, інакше котлін вже стане застарілим

А шо там по Valhalla?
Дуже чекаю на початок її використання і широкий адопшн.

Valhalla рухається вперед, скажу відверто. Але спочатку будуть зміни які не будуть помітні ззовні, лише зміни в JDK/JVM.

Да, я розумію, але коли буде вже саме апішні зміни? У якій версії планують публікувати?

Нужно ждать LTS хотя в целом неплохо что релизят

Чекати — вже не найефективніша стратегія. Треба брати приклад із великих екосистем типу Spring. Команда там вже працює над адаптацією нового функціоналу. Теж саме стосується стеку DataStax, там вже перевели Cassandra 4.x.x на JDK 19+. Тобто, чекати ще одного LTS не вигідно, краще і дешевше буде мати готову кодову базу під новий функціонал, а не наздоганяти потяг, що несеться у світле майбутнє Java. Якщо цікаво, то можемо поспілкуватися на цю тему.

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

Меня кстати обычно расстраивает гредл он не поддерживает последние версии обычно но не знаю как сейчас. Можно настроить но не без проблем.

Gradle взагалі якась пічаль, він досі не підтримує JDK 19, тобто, вже рік як нічого не робиться там. Тому очевидний вибір — mvn.

Що саме ви маєте на увазі? Підтримка 19 версії з 7.6 версії гредла

Беру свої слова назад. Так, дійсно, 7.6 від 24 лютого підтримує JDK 19. Мене більш турбує сама затримка у підтримці, наразі це 5+ місяців. Із мавеном ситуація зовсім інша.

А коли можна готуватись до так званого «великого релізу» ? Чи планується стандартний біндинг до Vulkan API ?

Великими релізами вважаються ті, що мають довгострокову підтримку. Наступний такий реліз — Java 21 (до цього була Java 17), тобто, за 6 місяців.

Чи планується стандартний біндинг до Vulkan API ?

Наразі ведеться робота над проектом Lanai, який буде мати підтримку і Vulkan, i Metal. Але давати якісь прогнози відносно того коли саме буде реалізовано та релізнуто — важно сказати. Персонально, із того що я бачу, можу сказати, що навіть зараз можна реалізувати Vulkan API на Java використовуючи Project Panama API, для початку цього буде достатньо. Якщо цікаво, то можемо окрепо поспілкуватися на цю тему.

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