Java 16 to kolejne wydanie przybliżające nas do edycji LTS. Do niej pozostało już około pół roku. Zobaczmy, co dostajemy już teraz. Co zatem kryje się w Java 16?

Java 16 – co w pudełku?
Tym razem liczba rozszerzeń do JDK, czyli JEP (ang. JDK Enhancement Proposal), jest nieco dłuższa. Mamy tutaj 17 zmian. Dla porównania, wcześniejsza edycja miała ich tylko 14. Poniżej zestawienie:
Obszar | JDK Enhancement Proposal (JEP) |
Rozszerzenia języka na stałe | 394: Pattern Matching for instanceof 395: Records |
Inkubator i Preview | 338: Vector API (Incubator) 389: Foreign Linker API (Incubator) 393: Foreign-Memory Access API (Third Incubator) 397: Sealed Classes (Second Preview) |
Ulepszenia dla JVM | 376: ZGC: Concurrent Thread-Stack Processing 387: Elastic Metaspace |
Lepsze IPC | 380: Unix-Domain Socket Channels |
Uwidocznienie niekompatybilności | 390: Warnings for Value-Based Classes 396: Strongly Encapsulate JDK Internals by Default |
Integracja portów | 386: Alpine Linux Port 388: Windows/AArch64 Port |
Nowe narzędzia | 392: Packaging Tool |
Uproszczenie rozwoju JDK | 347: Enable C++14 Language Features 357: Migrate from Mercurial to Git 369: Migrate to GitHub |
Przejdźmy do szczegółów.
Rozszerzenia języka na stałe
Java 16 przynosi nam w końcu finalne wersje dwóch bardzo fajnych mechanizmów. Oba mieliśmy dostępne w Preview od JDK 14.
Pierwszy to 394: Pattern Matching for instanceof. Ten pożyteczny składnik języka osiągnie maksimum potencjału w połączeniu z Sealed Classes. W obecnym wydaniu Sealed Classes są dostępne w ramach drugiego Preview (o tym dalej). Także możemy spodziewać się, że w wydaniu 17, czyli LTS, będziemy mogli już w pełni wykorzystać oba mechanizmy.
Drugi element to 395: Records. To cały czas moja ulubiona zmiana od dłuższego czasu w ramach JDK. Dlatego tym bardziej cieszę się, że w końcu mamy jej finalną wersję.
Na marginesie Spring świetnie działa z Records. Także naprawdę warto z tego mechanizmu korzystać, jeśli macie możliwość pracowania na tych nieco młodszych wersjach JDK.
Inkubator i Preview
W ramach inkubatora na początku mamy 338: Vector API (Incubator). Podstawowa idea tej zmiany to wprowadzenie API dla obliczeń wektorowych. Efektem ma być dużo lepsze przełożenie na obsługę na poziomie sprzętu.
389: Foreign Linker API (Incubator) to z kolei zmiana, która ma uprościć życie programistom korzystającym z natywnych bibliotek. Nowe API ma być lepszym rozwiązaniem od Java Native Interface (JNI). Nowe, czyli prostsze w obsłudze i generujące mniej błędów.
Z kolei wiecznie żywe, cieszące się złą sławą, sun.misc.Unsafe jest coraz bliżej końca. 393: Foreign-Memory Access API (Third Incubator) to próba wprowadzenia jednorodnego sposobu do dostępu do pamięci poza stertą. Ten JEP wprowadzany jest bardzo powoli, ale droga wydaje się już jasna i raczej nie zniknie on w najbliższej przyszłości.
Bez wątpienia 397: Sealed Classes (Second Preview) to zmiana pozwalająca nam programistom na zachowanie większej kontroli nad kodem. Dłuższy jej opis znalazł się w artykule opisującym Java 15, gdzie pojawiło się pierwsze Preview.
Ulepszenia dla JVM
W ramach 376: ZGC: Concurrent Thread-Stack Processing garbage collector ZGC dostaje zastrzyk zwiększający wydajność. Potencjał tej zmiany jest bardzo duży. Programiści JVM dążą w tym przypadku do możliwości w pełni współbieżnej obsługi stosu wątku poprzez zaprzestanie korzystana z mechanizmu safepoints w dużej części operacji przeprowadzanych przez garbage collector.
W dwóch słowach o safepoints. Safepoint jest to taki moment, w którym stan wątku jest ściśle ustalony. Oznacza to, że gdy wątek jest w trakcie wykonywania instrukcji, to JVM nie może założyć, że wątek jest w safepoint. jak widać, ZGC bazując wcześniej na safepoints, był niejako ograniczony do obsługi dla wątków, które były w tym stanie. Podsumowując teraz ZGC będzie miał więcej przestrzeni do działania, a co za tym idzie realizacja ideii ekstremalnie szybkich cyklów garbage collectora jest już bardzo blisko.
Kolejna zmiana, 387: Elastic Metaspace, to kolejna optymalizacja. Tym razem chodzi o metaspace, czyli obszar metadanych dotyczących naszych klas. Elastyczny metaspace to miejsce, które będzie oddawało niewykorzystaną pamięć RAM do systemu operacyjnego. Dla nas sam zysk np. w przypadku długofalowego utrzymania usług.
Lepsze IPC
Inter-process Communication (IPC), czyli komunikacja między lokalnymi procesami, w Java 16 będzie bardziej bezpieczna i trochę wydajniejsza dzięki 380: Unix-Domain Socket Channels. Unix-domain Socket są specjalnie zaprojektowane do wymiany między procesami w tym samym systemie. Co za tym idzie narzut, jaki w takiej komunikacji miały sockety TCP/IP, może zostać zredukowany. A skoro nawet wsparcie dla tego mechanizmu mamy już w Windows 10 i Windows Server 2019, to dlaczego JVM miałby z tego nie korzystać.
Uwidocznienie niekompatybilności
Kiedy użyjemy w Java 16 konstruktora klas przeznaczonych do reprezentowania wartości (np. wrappery typów prostych) lub w naszym kodzie będzie próba synchronizacji na nich wówczas pojawią się nam dodatkowe ostrzeżenia podczas kompilacji. A to wszystko dzięki 390: Warnings for Value-Based Classes.
JDK coraz bardziej enkapsuluje swój kod wewnętrzny. Aktualnie zrealizowane jest to poprzez JEP 396: Strongly Encapsulate JDK Internals by Default. Oczywiście dobroć ta nie dotyczy sun.misc.Unsafe.
Integracja portów w repozytorium
386: Alpine Linux Port i 388: Windows/AArch64 Port to zmiany organizacyjne. Porty na te platformy były już dostępne, jednak ich rozwój nie był związany z główną linią JDK. Od teraz będzie on z nią silnie zintegrowany.
Nowe narzędzia w Java 16
W ramach 392: Packaging Tool otrzymujemy nowe narzędzie jpackage. W związku z tym od teraz przygotowywanie paczek natywnych ma być szybkie, proste i przyjemne.
Uproszczenie rozwoju JDK
Trzy zmian 347: Enable C++14 Language Features, 357: Migrate from Mercurial to Git oraz 369: Migrate to GitHub mają przede wszystkim na celu uproszczenie rozwoju JDK dla jego developerów.
I tu w naturalny sposób od Java 16 programiści JDK będą mogli korzystać z nowych rozwiązań C++. Git i Github to też naturalny ruch. Mniejsza wielkość repozytorium, szybsza obsługa i zdecydowanie lepsze wsparcie narzędzi było z pewnością oczekiwanym ruchem.
Podsumowanie Java 16
Java 16 nie przynosi przełomowych nowości z punktu widzenia programistów.
Tak, jest w niej kilka ciekawych mechanizmów. Ale ich magia kryje się głęboko w wewnętrznym warstwach JDK.
W istocie cieszy obecność finalnej wersji Pattern Matching for instanceof oraz Records. Apetyt jest jednak na więcej.
Jak każdy non-LTS nie należy oczekiwać, że to konkretne wydanie zagości w aplikacjach korporacyjnych. Pamiętamy przecież, że mnóstwo kodu śmiga jeszcze na Java 8.
W każdym razie, Java 17 LTS jest coraz bliżej. Też czekasz na wydanie LTS?
O kolejnych wydaniach Javy możesz przeczytać w artykułach:
Cześć! Masz rację, większość aplikacji stoi na Javie 8 lub 11, stąd przychodzi mi tylko hobbistyczne pisanie kodu w nowszych wersjach Javy 😉 Pattern Matching for instanceof oraz Records naprawdę sprawiają, że kod jest czytelniejszy: brak zbędnych rzutowań czy też adnotacji Lomboka. Mam nadzieję, że przyjdzie mi niedługo kodować komercyjnie w oczekiwanej Javie 17!
Ja też mam taką nadzieję. Bardziej „domowe” rzeczy już u mnie na 17 chodzą od jakiegoś czasu. Natomiast sam jestem ciekawy, czy w 2021 już coś komercyjnie na edycji 17 będzie u mnie działać.