Po sześciu miesiącach opracowywania firma Oracle opublikowała platformę Java SE 23 (Java Platform, Standard Edition 23), której podstawową realizacją jest otwarty projekt OpenJDK. Z wyjątkiem usunięcia niektórych przestarzałych funkcji, Java SE 23 zachowuje zgodność wsteczną z poprzednimi wersjami platformy Java — większość wcześniej napisanych projektów Java będzie działała bez zmian na nowej wersji. Gotowe do instalacji pakiety Java SE 22 (JDK, JRE i Server JRE) przygotowano dla systemów Linux (x86_64, AArch64), Windows (x86_64) oraz macOS (x86_64, AArch64). Opracowana w ramach projektu OpenJDK podstawowa realizacja Java 23 jest całkowicie otwarta na licencji GPLv2 z wyjątkami GNU ClassPath, które pozwalają na dynamiczne wiązanie z komercyjnymi produktami.
Java SE 23 należy do kategorii wydań o standardowym okresie wsparcia, a aktualizacje będą wydawane do czasu następnego wydania. Jako wersję z długoterminowym wsparciem (LTS) należy używać Java SE 21 lub Java SE 17, dla których aktualizacje będą wydawane do 2031 i 2029 roku odpowiednio (publiczne — do 2028 i 2026 roku). Rozszerzone wsparcie dla LTS Java SE 8 potrwa do 2030 roku, a Java SE 11 — do 2032 roku.
Wśród nowości w Java SE 23 znajdują się:
- Domyślnie włączony jest generacyjny tryb pracy zbieracza śmieci ZGC (Generational Z Garbage Collector), który wykorzystuje oddzielne przetwarzanie „starych” i „młodych” obiektów, co zwiększa efektywność czyszczenia niedawno stworzonych obiektów o krótkim czasie życia. Zastosowanie Generational ZGC zmniejsza ryzyko wstrzymania podczas przydzielania zasobów, zmniejsza obciążenie CPU i zużycie pamięci podczas zbierania śmieci. Testowanie Generational ZGC z Apache Cassandra 4 wykazało czterokrotny wzrost przepustowości przy stałym rozmiarze sterty (heap) oraz zmniejszenie rozmiaru sterty o jedną czwartą przy niezmiennej przepustowości.
- Do JavaDoc dodano wsparcie dla użycia składni Markdown do dokumentowania kodu w komentarzach, którą można stosować zamiast mieszanki HTML i tagów @ JavaDoc.

- Mechanizmy dopasowania z wzorem wzbogacono wstępnym wsparciem dla użycia typów prymitywnych (int, byte, char i inne podstawowe typy, które nie są obiektami) we wszystkich typach szablonów, w operatorze „instanceof” oraz w blokach „switch”. switch (x.getStatus()) { case 0 -> „okej”; case 1 -> „ostrzeżenie”; case 2 -> „błąd”; case int i -> „nieznany status: ” + i; } if (i instanceof byte b) { … b … }
- Dodano wstępną obsługę używania jednego wyrażenia „import module M” do importowania od razu wszystkich pakietów eksportowanych przez wskazany moduł. Zmiana ta znacząco upraszcza ponowne wykorzystanie bibliotek modułowych, umożliwiając podłączenie bibliotek i klas bez określania ich miejsca w hierarchii pakietów. Na przykład, wskazanie „import module java.base” spowoduje import wszystkich 54 pakietów wchodzących w skład modułu java.base, które wcześniej należałoby wymieniać oddzielnie („import java.io.*”, „import java.util.*” itp.).
Zaprezentowano drugą wstępną implementację API Class-File do analizy, generowania i przekształcania plików z klasami 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); } } });
- Zaprezentowano ósme wstępne wdrożenie API Vector, które oferuje funkcje do obliczeń wektorowych, wykonywanych przy użyciu instrukcji wektorowych procesorów x86_64 i AArch64, co umożliwia jednoczesne zastosowanie operacji do wielu wartości (SIMD). W przeciwieństwie do możliwości automatycznej wektoryzacji operacji skalarnych oferowanych w JIT-kompilatorze HotSpot, nowe API umożliwia wyraźne zarządzanie wektoryzacją w celu równoległego przetwarzania danych.
- W klasie java.io.Console dodano metody format, printf, readPassword i readLine do formatowania, wyświetlania i odczytywania tekstu z uwzględnieniem wybranej lokalizacji. System.console().printf(Locale.FRANCE, „%1$tY-%1$tB-%1$te %1$tA”, new Date()) 2024-mai-16 jeudi
- Dodano drugie wstępne wdrożenie rozszerzonego API Stream, które obsługuje definiowanie własnych operacji pośrednich, które mogą być przydatne w przypadkach, gdy istniejące wbudowane operacje pośrednie nie są wystarczające do pożądanego przekształcenia danych. Własne przetworniki są podłączane za pomocą nowej operacji pośredniej Stream::gather(Gatherer), która przetwarza elementy strumienia, stosując do nich przetwornik określony przez użytkownika. 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]]
- Dodano trzecie wstępne wdrożenie niejawnie zadeklarowanych klas i anonimowych instancji metody „main”, w których można obejść się bez deklaracji public/static, przekazywania tablicy argumentów i innych bytów związanych z deklarowaniem klasy. // było public class HelloWorld { public static void main(String[] args) { System.out.println("Hello world!"); } } // teraz można void main() { System.out.println("Hello, World!"); }
- Dodano drugi wstępny wariant możliwości, która pozwala na podawanie w konstruktorach wyrażeń przed wywołaniem super(…), używanego do jawnego wywoływania konstruktora klasy nadrzędnej z konstruktora klasy dziedziczącej, jeśli te wyrażenia nie odnoszą się do tworzony przez konstruktor instancji. class Outer { void hello() { System.out.println("Hello"); } class Inner { Inner() { hello(); super(); } } }
- Dodano trzecie wstępne wdrożenie ograniczonych wartości (Scoped Values), które pozwalają na współdzielenie niezmiennych danych w strumieniach i efektywną wymianę danych między wątkami potomnymi (wartości są dziedziczone). Ograniczone wartości rozwijają się w celu zastąpienia mechanizmu zmiennych lokalnych dla wątku (thread-local variables) i są bardziej efektywne przy używaniu bardzo dużej liczby wirtualnych wątków (tysiące i miliony wątków). Główna różnica między ograniczonymi wartościami a zmiennymi lokalnymi dla wątku polega na tym, że pierwsze są zapisywane tylko raz, później nie mogą być zmieniane i pozostają dostępne tylko podczas wykonywania wątku.
- Zaproponowano trzeci wstępny wariant API dla strukturalnego współbieżności (Structured Concurrency), co upraszcza rozwój aplikacji wielowątkowych poprzez obsługę kilku zadań realizowanych w różnych wątkach jako jednego bloku.
- Zdeprecjonowane i planowane do usunięcia zostały metody dostępu do pamięci zewnętrznej (poza JVM) udostępniane przez klasę sun.misc.Unsafe. Do dostępu do pamięci poza stertą (off-heap) oraz interakcji z zewnętrznym kodem zaleca się korzystanie z API VarHandle oraz API FFM (Foreign Function & Memory).
Dodatkowo warto zauważyć publikację aktualizacji platformy do tworzenia aplikacji z interfejsem graficznym JavaFX 23 oraz włączenie kompilatora JIT GraalVM do podstawowej wersji Oracle JDK 23.
Przedstawiono również nową wersję uniwersalnej maszyny wirtualnej GraalVM, która obsługuje uruchamianie aplikacji w JavaScript (Node.js), Pythonie, Ruby, R, w dowolnych językach dla JVM (Java, Scala, Clojure, Kotlin) oraz w językach, dla których można generować kod bitowy LLVM (C, C++, Rust). Oprócz wsparcia dla JDK 23 w nowej wersji przeprowadzono optymalizację zużycia pamięci i rozmiaru kodu wykonywalnego, a także wprowadzono pełne wsparcie dla osadzania Pythona i WebAssembly w kodzie Java z użyciem kompilacji JIT.
Źródło: opennet.ru

