Java 16 – co nowego?

16 marca wysz艂a 16 wersja Javy. 馃檪 W ko艅cu zobaczymy rekordy jako oficjaln膮 cz臋艣膰 j臋zyka! Zosta艂o wprowadzone m.in. Vector API jako Incubator oraz prowadzone s膮 prac臋 nad popraw膮 wsp贸艂pracy Javy z natywnym kodem. Nie przed艂u偶aj膮c wst臋pu, zobaczmy jakie nowe zabawki otrzymamy w tej wersji!

Vector API (Incubator)

Normalnie procesor wykonuje jedn膮 operacj臋 na jednym zestawie danych (SIMD – Single Instruction Single Data). Czyli przyk艂adowo mo偶e doda膰 do siebie dwie liczby. Wektory pozwalaj膮 na wykonanie operacji na wielu liczbach naraz (SIMD -Single Instruction Multipe Data). Wirtualna maszyna Javy ju偶 wcze艣niej posiada艂a optymalizacj臋, kt贸ra automatycznie potrafi艂a zmienia膰 kod, aby wykorzysta膰 mo偶liwo艣ci procesora operuj膮cego na wektorach. Jednak mo偶liwo艣ci te s膮 ograniczone i delikatne. Nowe API odda w r臋ce programist贸w wi臋ksz膮 kontrol臋 nad procesem, dzi臋ki temu b臋dziemy mogli wprowadzi膰 takie optymalizacje sami, w wi臋kszej ilo艣ci miejsc.

Dokumentacja podaje przyk艂ad p臋tli, kt贸r膮 mo偶emy zoptymalizowa膰. P臋tla wygl膮da nast臋puj膮co:

void scalarComputation(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
}
}
view raw VectorApiBefore.java hosted with ❤ by GitHub

Oraz wersja z wykorzystaniem API wektorowego.

static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256;
void vectorComputation(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i += SPECIES.length()) {
var m = SPECIES.indexInRange(i, a.length);
// FloatVector va, vb, vc;
var va = FloatVector.fromArray(SPECIES, a, i, m);
var vb = FloatVector.fromArray(SPECIES, b, i, m);
var vc = va.mul(va).
add(vb.mul(vb)).
neg();
vc.intoArray(c, i, m);
}
}
view raw VectorApi.java hosted with ❤ by GitHub

Wi臋cej przyk艂ad贸w mo偶ecie znale藕膰 na stronie https://openjdk.java.net/jeps/338

Rekordy

W du偶ym uproszczeniu jest to nowy typ klasy do przechowywania niemutowalnego stanu. Dzi臋ki temu w bardzo zwi臋z艂y spos贸b mo偶emy zadeklarowa膰 klas臋 z polami, do kt贸rej automatycznie zostan膮 dodane gettery, konstruktor, metody equals, hashCode i toString. Pierwszy raz pojawi艂y si臋 w Javie 14 jako preview, nast臋pnie w Javie 15 zosta艂y oznaczone jako second preview. W aktualnej wersji wchodz膮 ju偶 oficjalnie do j臋zyka. Szerzej pisa艂em o nich w oddzielnym po艣cie: Java 14 鈥 Record classes. Wi臋cej mo偶ecie przeczyta膰 te偶 na oficjalnej stronie: https://openjdk.java.net/jeps/395.

Pattern Matching for instanceof

Podobnie jak rekordy, pattern matching for instanceof pierwszy raz ujrzeli艣my w Javie 14. Dzi臋ki temu mo偶emy zadeklarowa膰 zmienn膮 od razu przy sprawdzeniu, czy jest odpowiedniego typu. W poni偶szym przyk艂adzie u偶ywamy od razu zmiennej w instrukcji if, aby sprawdzi膰, czy ma odpowiedni膮 d艂ugo艣膰.

if (obj instanceof String s && s.length() > 5) {
return s.contains("Yes!");
}

Wi臋cej mo偶ecie przeczyta膰 w poprzednim wpisie: Java 14 鈥 Co nowego w kolejnym wydaniu? oraz na oficjalnej stronie: https://openjdk.java.net/jeps/394.

Elastic Metaspace

Nieu偶ywana pami臋膰 na metadane klasy b臋dzie zwracana do systemu. W przesz艂o艣ci zdarza艂o si臋, 偶e metaspace w JVM zajmowa艂 przesadnie du偶o pami臋ci. Nawet gdy by艂a ona ju偶 niepotrzebna, nadal nie by艂a zwracana do systemu. W nowej wersji kod zarz膮dzaj膮cy t膮 cz臋艣ci膮 pami臋ci zosta艂 uproszczony oraz zmieni艂 si臋 wykorzystywany algorytm, dzi臋ki czemu mo偶liwe jest zwolnienie pami臋ci. Wi臋cej mo偶ecie znale藕膰 na stronie: https://openjdk.java.net/jeps/387.

Unix-Domain Socket Channels

Dodanie wsparcia dla Unix-domain socket. S膮 one u偶ywane do komunikacji pomi臋dzy procesami (IPC – Inter-process communication). S膮 bardzo podobne do socket贸w TCP/IP, z t膮 r贸偶nic膮, 偶e s膮 adresowane za pomoc膮 艣cie偶ek w systemie plik贸w zamiast adres贸w IP. Je艣li chodzi o odczyt i zapis, to b臋d膮 one si臋 zachowywa膰 tak samo, akceptacja przychodz膮cych po艂膮cze艅, multipleksacja i inne operacje b臋d膮 dzia艂a艂y tak samo. Dzi臋ki temu b臋dzie mo偶na w bezpieczniejszy i wydajniejszy spos贸b komunikowa膰 si臋 pomi臋dzy procesami ni偶 przez po艂膮czenie loopback TCP/IP. Wi臋cej mo偶ecie przeczyta膰 na stronie https://openjdk.java.net/jeps/380.

Sealed Classes (Second Preview)

Klasy zapiecz臋towne pojawi艂y si臋 ju偶 w Javie 15, w tym wydaniu s膮 oznaczone jako drugi preview. Dzi臋ki temu mo偶emy ustali膰 jakie klasy b臋d膮 dziedziczy艂y po naszej klasie lub implementowa艂y interfejs. W przysz艂o艣ci r贸wnie偶 b臋dzie mo偶liwy lepszy pattern matching (np. b臋dziemy mogli tworzy膰 wyczerpuj膮ce switche na podstawie typu klasy).

Przyk艂ad klas zapiecz臋towanych poni偶ej. Warto zauwa偶y膰, 偶e klasa Square dziedzicz膮ca po zapiecz臋towanej klasie Shape jest ju偶 non-sealed, oznacza to, 偶e po niej mog膮 dziedziczy膰 inne klasy bez ogranicze艅, mimo 偶e klasa nadrz臋dna Shape by艂a oznaczona jako sealed.

package com.example.geometry;
public abstract sealed class Shape
permits Circle, Rectangle, Square { ... }
public final class Circle extends Shape { ... }
public sealed class Rectangle extends Shape
permits TransparentRectangle, FilledRectangle { ... }
public final class TransparentRectangle extends Rectangle { ... }
public final class FilledRectangle extends Rectangle { ... }
public non-sealed class Square extends Shape { ... }
view raw Sealed.java hosted with ❤ by GitHub

Wi臋cej mo偶ecie przeczyta膰 na stronie https://openjdk.java.net/jeps/397.

Porty dla Alpine Linux i Windows/AArch64

Przygotowanie portu JDK dla dystrybucji Alpine Linux, kt贸ry u偶ywa musl jako biblioteki C dla architektury x64 i AArch64. Alpine Linux jest cz臋sto wykorzystywany w deploymentach w chmurze i kontenerach dzi臋ki temu, 偶e obraz jest bardzo ma艂y. Przyk艂adowo dockerowy obraz zajmuje mniej ni偶 6MB. Wi臋cej tutaj: https://openjdk.java.net/jeps/386.

Drugim portem jest port dla Windowsa dzia艂aj膮cego na architekturze AArch64 (ARM64). Architektura ta nabiera coraz wi臋kszej popularno艣ci, dlatego zdecydowano si臋 doda膰 dla niej port. Wi臋cej mo偶ecie znale藕膰 tutaj: https://openjdk.java.net/jeps/388.

Foreign Linker API (Incubator)

Nowe API ma pozwala膰 na 艂atwiejszy, czysto Javovy dost臋p do natywnego kodu. Razem z Foreign Memory Access API maj膮 zast膮pi膰 mechanizm JNI. Ma by膰 te偶 co najmniej tak szybkie jak JNI. Wi臋cej znajdziecie tutaj: https://openjdk.java.net/jeps/389.

Foreign-Memory Access API (Third Incubator)

Foreign Memory Access API ma zapewni膰 szybki i bezpieczny dost臋p do pami臋ci natywnej. Aktualnie mo偶emy si臋 do niej dosta膰 poprzez Unsafe, co jak sama nazwa wskazuje, jest niebezpieczne. Drug膮 mo偶liwo艣ci膮 jest wykorzystanie DirectByteBuffer, co jest bezpieczne, jednak to API nie jest zaprojektowane jako API do og贸lnej pracy z pami臋ci膮. Je艣li czytamy lub zapisujemy cz臋sto ma艂e porcje danych to sprawdzanie, czy nie wychodzimy poza zaalokowan膮 pami臋膰 (bound checks) mo偶e zajmowa膰 wi臋kszo艣膰 czasu procesora. Nowe API b臋dzie to mocno optymalizowa膰, na przyk艂ad je艣li robimy odczyty w p臋tli, takie sprawdzenia zostan膮 wyniesione poza p臋tl臋 i wykonane tylko raz. Wi臋cej przeczytacie tutaj: https://openjdk.java.net/jeps/393.

Inne zmiany

Do nowego wydania wesz艂o te偶 du偶o zmian, kt贸re nie b臋d膮 dla nas widoczne w codziennej pracy:

  • Enable C++14 Language Features – w kodzie 藕r贸d艂owym C++ do JDK b臋dzie mo偶na u偶ywa膰 funkcjonalno艣ci z C++ 14 (https://openjdk.java.net/jeps/347).
  • Migrate from Mercurial to Git – kod 藕r贸d艂owy OpenJDK b臋dzie trzymany teraz w Gicie zamiast Mercuriala (https://openjdk.java.net/jeps/357).
  • Migrate to GitHub – repozytoria z kodem 藕r贸d艂owym do OpenJDK i wszystkich projekt贸w b臋d膮 zmigrowane do GitHuba dla wersji 11 i p贸藕niejszych (https://openjdk.java.net/jeps/369),
  • Strongly Encapsulate JDK Internals by Default – w JDK 9 jako default by艂a rozlu藕niona enkapsulacja, w 16 domy艣lnie b臋dzie silna. Mo偶na to oczywi艣cie zmieni膰, jednak ma to zach臋ci膰 programist贸w do u偶ywania standardowego API zamiast wewn臋trznych mechanizm贸w JDK. Na razie krytyczne API takie jak Unsafe pozostanie dost臋pne.
  • ZGC: Concurrent Thread-Stack Processing – kolejne ulepszenie ZGC – przeniesienie procesowania stosu w膮tku z safepointu do fazy r贸wnoleg艂ej. Przy du偶ej ilo艣ci w膮tk贸w wyszukiwanie korzeni mo偶e robi膰 si臋 problematyczne i zabiera膰 du偶o czasu. Przeniesienie tej operacji do fazy r贸wnoleg艂ej powinno zmniejszy膰 czas pauz GC. Wi臋cej tutaj: https://openjdk.java.net/jeps/376.
  • Warnings for Value-Based Classes – u偶ywanie konstruktor贸w klas opakowuj膮cych typy prymitywne b臋dzie generowa艂o ostrze偶enia przy kompilacji. R贸wnie偶 pr贸ba synchronizacji opartej na tych klasach b臋dzie generowa艂o ostrze偶enie. Klasy te w przysz艂o艣ci maj膮 sta膰 si臋 value-based classes. Czyli obiekt b臋dzie definiowany przez jego warto艣膰. Czym s膮 value-based classes mo偶esz przeczytac tutaj: https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/doc-files/ValueBased.html, a o samych zmianach w Javie tutaj: https://openjdk.java.net/jeps/390.
  • Packaging Tool – narz臋dzie do przygotowywania natywnych paczek aplikacji (msi/exe dla Windowsa, pkg/dmg dla MacOS i deb/rpm dla Linuxa). Jest to rozwini臋cie javapackager tool znanego z JavaFX. Pierwszy raz pojawi艂o si臋 w Javie 14 jako Incubation, w tej wersji wchodzi ju偶 jako pe艂na funkcjonalno艣膰. Wi臋cej tutaj: https://openjdk.java.net/jeps/392.

Podsumowanie

To ju偶 wszystko, co znajdziemy w nowej Javie. Nowa wersja pojawiaj膮ca si臋 co p贸艂 roku bardzo przy艣pieszy艂a wprowadzanie zmian w j臋zyku. Czekam niecierpliwie na og艂oszenie kolejnych ulepsze艅 w przysz艂o艣ci.

Dodaj komentarz

Tw贸j adres e-mail nie zostanie opublikowany. Wymagane pola s膮 oznaczone *