JDK 16: Nowe funkcje w Javie 16

Java Development Kit (JDK) 16 osiągnął początkową fazę zwalniania, co oznacza, że ​​zestaw funkcji jest teraz zamrożony od 10 grudnia 2020 r. Nowe funkcje w JDK 16 obejmują drugi podgląd zapieczętowanych klas, dopasowywanie wzorców po współbieżne wątki. przetwarzanie stosu do usuwania elementów bezużytecznych.

JDK 16 będzie referencyjną implementacją standardowej wersji Java, która będzie następować po JDK 15, która pojawiła się 15 września. Proponowany harmonogram wydań zakłada, że ​​JDK 16 osiągnie drugą fazę zwalniania 14 stycznia 2021 r., Po czym kandydaci do wydania pojawią się 4 lutego i 18 lutego 2021. Wydanie produkcyjne ma zostać opublikowane 16 marca 2021 roku.

Siedemnaście propozycji oficjalnie dotyczy JDK 16 na dzień 10 grudnia 2020 r. Nowe możliwości, które pojawią się w Javie 16, obejmują:

  • Propozycja ostrzeżeń dla klas opartych na wartościach wyznacza pierwotne klasy opakowania jako oparte na wartości i wycofuje ich konstruktory do usunięcia, powodując pojawienie się nowych ostrzeżeń o wycofaniu. Ostrzeżenia dotyczą niewłaściwych prób synchronizacji w wystąpieniach klas opartych na wartościach na platformie Java. Siłą napędową tych wysiłków jest Projekt Valhalla, który dąży do znacznego udoskonalenia modelu programowania Java w postaci klas prymitywnych. Klasy prymitywne deklarują, że instancje są wolne od tożsamości i mogą zawierać reprezentacje wbudowane lub spłaszczone, w których instancje można swobodnie kopiować między lokalizacjami pamięci i kodować przy użyciu wartości pól instancji.Projekt i implementacja klas prymitywnych w Javie jest teraz na tyle dojrzała, że ​​migrację niektórych klas platformy Java do klas pierwotnych można przewidzieć w przyszłej wersji. Kandydaci do migracji są nieformalnie określani jako klasy oparte na wartościach w specyfikacjach API.
  • Zapieczętowane klasy i interfejsy, które były wcześniej prezentowane w JDK 15, ograniczają, które inne klasy i interfejsy mogą je rozszerzać lub implementować. Cele planu obejmują umożliwienie autorowi klasy lub interfejsu kontrolowania kodu odpowiedzialnego za jego implementację, zapewnienie bardziej deklaratywnego sposobu ograniczania użycia nadklasy niż modyfikatory dostępu oraz wspieranie przyszłych kierunków w dopasowywaniu wzorców poprzez zapewnienie analiza wzorców.
  • Silne hermetyzacja wewnętrznych elementów JDK, z wyjątkiem krytycznych wewnętrznych interfejsów API, takich jak misc.Unsafe. Użytkownicy mogą wybrać złagodzoną silną enkapsulację, która jest domyślna od czasu JDK 9. Cele tej propozycji obejmują poprawę bezpieczeństwa i łatwości utrzymania JDK, jako części projektu Jigsaw, oraz zachęcanie programistów do migracji z używania elementów wewnętrznych do używania standardowych interfejsów API, tak że zarówno programiści, jak i użytkownicy końcowi mogą łatwo aktualizować do przyszłych wersji Java. Ta propozycja niesie ze sobą podstawowe ryzyko, że istniejący kod Java nie zadziała. Zachęcamy programistów do korzystania z narzędzia jdeps do identyfikowania kodu zależnego od wewnętrznych elementów JDK i przełączania się na standardowe zamienniki, jeśli są dostępne. Programiści mogą użyć istniejącej wersji, takiej jak JDK 11, do testowania istniejącego kodu przy użyciu --illegal-access=warndo identyfikowania elementów wewnętrznych, do których można uzyskać dostęp poprzez refleksję, używania  --illegal-access=debugdo wskazywania błędnego kodu i testowania za pomocą --illegal-access=deny.
  • Zagraniczne API konsolidatora, oferujące statycznie wpisywany dostęp w czystej Javie do kodu natywnego. To API będzie w fazie inkubatora w JDK 16. Wraz z proponowanym API dostępu do pamięci obcej, API obcego konsolidatora znacznie uprości podatny na błędy proces wiązania się z biblioteką natywną. Plan ten ma na celu zastąpienie JNI (Java Native Interface) lepszym modelem programowania w czystym języku Java, oferowanie obsługi języka C, a z czasem zapewnienie wystarczającej elastyczności, aby dostosować się do obsługi innych platform, takich jak 32-bitowe x86 i funkcje obce napisane w językach innych niż C, na przykład C ++. Wydajność powinna być lepsza lub porównywalna z JNI.
  • Przenoszenie przetwarzania stosu wątków ZGC (Z Garbage Collector) z punktów bezpieczeństwa do fazy równoczesnej. Cele tego planu obejmują usunięcie przetwarzania stosu wątków z punktów bezpieczeństwa ZGC; sprawianie, że przetwarzanie stosu jest leniwe, kooperatywne, współbieżne i przyrostowe; usuwanie wszystkich innych przetwarzania głównego wątku z punktów bezpieczeństwa ZGC; oraz zapewnienie mechanizmu dla innych podsystemów HotSpot VM do leniwego przetwarzania stosów. ZGC ma sprawić, że przerwy w GC i problemy ze skalowalnością w HotSpot należą do przeszłości. Jak dotąd operacje GC, które skalują się wraz z rozmiarem sterty i rozmiarem metaprzestrzeni, zostały przeniesione z operacji punktu bezpiecznego do równoległych faz. Obejmowały one oznaczanie, przenoszenie, przetwarzanie referencji, usuwanie klas i większość przetwarzania root.Jedyne czynności, które nadal są wykonywane w punktach bezpieczeństwa GC, to podzbiór przetwarzania głównego i ograniczona czasowo operacja zakończenia oznaczania. Te korzenie obejmują stosy wątków Java i inne korzenie wątków, przy czym te korzenie są problematyczne, ponieważ skalują się wraz z liczbą wątków. Aby wyjść poza obecną sytuację, przetwarzanie na wątek, w tym skanowanie stosu, musi zostać przeniesione do fazy współbieżnej. W tym planie koszt przepustowości ulepszonego opóźnienia powinien być nieznaczny, a czas spędzony w punktach bezpieczeństwa ZGC na typowych maszynach powinien być krótszy niż jedna milisekunda.musi zostać przeniesiony do równoległej fazy. W tym planie koszt przepustowości ulepszonego opóźnienia powinien być nieznaczny, a czas spędzony w punktach bezpieczeństwa ZGC na typowych maszynach powinien być krótszy niż jedna milisekunda.muszą zostać przeniesione do równoległej fazy. W tym planie koszt przepustowości ulepszonego opóźnienia powinien być nieznaczny, a czas spędzony w punktach bezpieczeństwa ZGC na typowych maszynach powinien być krótszy niż jedna milisekunda.
  • Elastyczna funkcja metaprzestrzeni, która szybciej zwraca nieużywaną pamięć metadanych klasy HotSpot VM (metaprzestrzeń) do systemu operacyjnego, zmniejsza ilość zajmowaną przez metaprzestrzeń i upraszcza kod metaprzestrzeni w celu zmniejszenia kosztów utrzymania. Metaspace miał problemy z wysokim wykorzystaniem pamięci poza stertą. Plan zakłada zastąpienie istniejącego alokatora pamięci schematem alokacji opartym na znajomych, zapewniając algorytm dzielenia pamięci na partycje w celu zaspokojenia żądań pamięci. Podejście to zostało zastosowane w miejscach takich jak jądro Linuksa i sprawi, że przydział pamięci na mniejsze fragmenty będzie praktycznym rozwiązaniem, aby zmniejszyć obciążenie modułu ładującego klasy. Zmniejszona zostanie również fragmentacja. Ponadto zaangażowanie pamięci z systemu operacyjnego w areny zarządzania pamięcią będzie wykonywane leniwie, na żądanie,w celu zmniejszenia zajmowanego miejsca przez ładowarki, które zaczynają od dużych aren, ale nie używają ich od razu lub mogą nie wykorzystywać ich w pełnym zakresie. Aby w pełni wykorzystać elastyczność oferowaną przez alokację znajomych, pamięć metaprzestrzeni zostanie zorganizowana w jednorodne granulki, które mogą być zatwierdzane i niezatwierdzane niezależnie od siebie.
  • Włączenie funkcji języka C ++ 14 w celu umożliwienia korzystania z funkcji C ++ 14 w kodzie źródłowym JDK C ++ i udzielenia szczegółowych wskazówek dotyczących tego, które z tych funkcji mogą być używane w kodzie HotSpot VM. W JDK 15 funkcje językowe używane przez kod C ++ w JDK zostały ograniczone do standardów językowych C ++ 98/03. Wraz z JDK 11, kod źródłowy został zaktualizowany, aby obsługiwał budowanie z nowszymi wersjami standardu C ++. Obejmuje to możliwość kompilowania z najnowszymi wersjami kompilatorów, które obsługują funkcje języka C ++ 11/14. Ta propozycja nie proponuje żadnych zmian stylu ani użytkowania dla kodu C ++, który jest używany poza HotSpot. Jednak aby skorzystać z funkcji języka C ++, wymagane są pewne zmiany w czasie kompilacji, w zależności od kompilatora platformy.
  • Vector API na etapie inkubatora, w którym JDK byłby wyposażony w moduł inkubatora, jdk.incubator.vector, aby wyrazić obliczenia wektorowe, które kompilują się do optymalnych instrukcji sprzętowych wektorowych na obsługiwanych architekturach procesorów, w celu uzyskania lepszej wydajności niż równoważne obliczenia skalarne. Vector API zapewnia mechanizm do pisania złożonych algorytmów wektorowych w Javie, wykorzystując wcześniej istniejącą obsługę maszyny wirtualnej HotSpot do wektoryzacji, ale z modelem użytkownika, który sprawia, że ​​wektoryzacja jest bardziej przewidywalna i niezawodna. Cele propozycji obejmują zapewnienie jasnego i zwięzłego interfejsu API do wyrażania szeregu obliczeń wektorowych, niezależność od platformy dzięki obsłudze wielu architektur procesorów oraz oferowanie niezawodnej kompilacji i wydajności środowiska uruchomieniowego na architekturach x64 i AArch64. Wdzięczna degradacja jest również celem,w których obliczenia wektorowe uległyby z wdziękiem degradacji i nadal działałyby, gdyby nie można ich było w pełni wyrazić w czasie wykonywania jako sekwencja sprzętowych instrukcji wektorowych, ponieważ architektura nie obsługuje niektórych instrukcji lub inna architektura procesora nie jest obsługiwana.
  • Przeniesienie JDK na platformę Windows / AArch64. Wraz z wydaniem nowego sprzętu klasy serwerowej i konsumenckiej AArch64 (ARM64), Windows / AArch64 stał się ważną platformą ze względu na popyt. Chociaż samo przenoszenie jest już w większości zakończone, celem tej propozycji jest integracja portu z głównym repozytorium JDK.
  • Przenoszenie JDK do Alpine Linux i do innych dystrybucji Linuksa, które używają musl jako podstawowej biblioteki C, na architekturach x64 i AArch64. Musl to Linux implementacja standardowej funkcjonalności biblioteki opisanej w standardach ISO C i Posix. Alpine Linux jest szeroko stosowany we wdrożeniach w chmurze, mikrousługach i środowiskach kontenerowych ze względu na niewielki rozmiar obrazu. Obraz platformy Docker dla systemu Linux jest mniejszy niż 6 MB. Pozwolenie, aby Java działała natychmiast po zainstalowaniu w takich ustawieniach, pozwoli Tomcat, Jetty, Spring i innym popularnym frameworkom na natywną pracę w tych środowiskach. Używając jlink do zmniejszenia rozmiaru środowiska wykonawczego Java, użytkownik może utworzyć jeszcze mniejszy obraz dostosowany do uruchamiania określonej aplikacji.
  • Dostarczanie klas rekordów, które działają jako przezroczyste nośniki niezmiennych danych. Rekordy można uznać za nominalne krotki. Rekordy były przeglądane w JDK 14 i JDK 15. Ten wysiłek jest odpowiedzią na skargi, że Java jest zbyt gadatliwa lub ma zbyt wiele ceremonii. Cele planu obejmują opracowanie konstrukcji zorientowanej obiektowo, która wyraża prostą agregację wartości, pomagając programistom skupić się na modelowaniu niezmiennych danych zamiast rozszerzalnego zachowania, automatycznym wdrażaniu metod opartych na danych, takich jak equalsi akcesory, oraz zachowaniu długotrwałych zasad Java, takich jak nominalne pisanie na maszynie.
  • Dodanie kanałów gniazda domeny uniksowej, w których obsługa gniazd w domenie uniksowej (AF_UNIX) jest dodana do funkcji API kanału gniazda i kanału gniazda serwera w pakiecie nio.channels. Plan rozszerza również mechanizm dziedziczonych kanałów o obsługę kanałów gniazd w domenie uniksowej i kanałów gniazda serwera. Gniazda domeny unix są używane do komunikacji między procesami na tym samym hoście. Pod wieloma względami są podobne do gniazd TCP / IP, z tym wyjątkiem, że są adresowane przez nazwy ścieżek systemu plików, a nie adresy IP i numery portów. Celem nowej możliwości jest obsługa wszystkich funkcji kanałów gniazd domeny unix, które są wspólne dla głównych platform Unix i Windows. Kanały gniazd w domenie uniksowej będą zachowywać się tak samo jak istniejące kanały TCP / IP pod względem zachowania odczytu / zapisu, konfiguracji połączenia, akceptacji połączeń przychodzących przez serwery,oraz multipleksowanie z innymi nieblokującymi kanałami do wyboru w selektorze. Gniazda domeny unix są bezpieczniejsze i wydajniejsze niż połączenia zwrotne TCP / IP w lokalnej komunikacji między procesami.
  • Interfejs API dostępu do pamięci obcej, umożliwiający programom Java bezpieczny dostęp do pamięci obcej poza stertą Java. Wcześniej inkubowany zarówno w JDK 14, jak i JDK 15, API dostępu do pamięci obcej byłby ponownie inkubowany w JDK 16, dodając udoskonalenia. Wprowadzono zmiany, w tym wyraźniejszy rozdział ról między interfejsami MemorySegmenti MemoryAddresses. Cele tej propozycji obejmują zapewnienie pojedynczego interfejsu API do działania na różnych rodzajach pamięci obcej, w tym natywnej, trwałej i zarządzanej pamięci sterty. Interfejs API nie powinien zagrażać bezpieczeństwu maszyny JVM. Motywacją do propozycji jest to, że wiele programów Java ma dostęp do pamięci obcej, takich jak Ignite, Memcached i MapDB. Jednak API Java nie zapewnia zadowalającego rozwiązania w zakresie dostępu do pamięci obcej.
  • Dopasowywanie wzorców dla instanceofoperatora, które również było podglądane zarówno w JDK 14, jak i JDK 15. Zostałoby sfinalizowane w JDK 16. Dopasowywanie wzorców pozwala na bardziej zwięzłe i bardziej zwięzłe wyrażenie wspólnej logiki programu, a mianowicie warunkowej ekstrakcji komponentów z obiektów. bezpiecznie.
  • Udostępnianie narzędzia jpackage do pakowania samodzielnych aplikacji Java. Wprowadzony jako narzędzie do inkubacji w JDK 14, jpackage pozostał w inkubacji w JDK 15. Wraz z JDK 16 jpackage przenosi się do produkcji, obsługując natywne formaty pakietów, aby zapewnić użytkownikom naturalne wrażenia podczas instalacji i umożliwić określenie parametrów uruchamiania podczas pakowania. Formaty obejmują msi i exe w systemie Windows, pkg i dmg w systemie MacOS oraz deb i rpm w systemie Linux. Narzędzie można wywołać bezpośrednio z wiersza poleceń lub programowo. Nowe narzędzie do tworzenia pakietów jest odpowiedzią na sytuację, w której wiele aplikacji Java musi zostać zainstalowanych na platformach natywnych w pierwszorzędny sposób, zamiast umieszczać je na ścieżce klasy lub ścieżce modułu. Potrzebny jest pakiet do zainstalowania odpowiedni dla platformy natywnej.
  • Migracja repozytoriów kodu źródłowego OpenJDK z Mercurial do Git. Napędzanie tych wysiłków to zalety związane z rozmiarem metadanych systemu kontroli wersji oraz dostępnymi narzędziami i hostingiem.
  • Migracja do GitHub, związana z migracją Mercurial-to-Git, z repozytoriami kodu źródłowego JDK 16 do umieszczenia w popularnym serwisie do udostępniania kodu. Wydania funkcji JDK i wydania aktualizacji JDK dla języka Java 11 i nowszych będą częścią tego planu. Przejście do Git, GitHub i Skara dla Mercurial JDK i JDK-sandbox nastąpiło 5 września i jest otwarte na wkład.  

Wersje JDK 16 dostępne we wczesnym dostępie dla systemów Linux, Windows i MacOS można znaleźć pod adresem jdk.java.net. Podobnie jak JDK 15, JDK 16 będzie wersją krótkoterminową, obsługiwaną przez sześć miesięcy. JDK 17, który ma się ukazać we wrześniu 2021 r., Będzie wydaniem długoterminowego wsparcia (LTS), które otrzyma wsparcie przez kilka lat. Obecna wersja LTS, JDK 11, została wydana we wrześniu 2018 roku.