Co je nového v Javě 17?
Dne 14. září 2021 byla uvedena na trh verze Java 17, označovaná jako Long-Term-Support (LTS), spolu s běhovou platformou Java. Podívejme se blíže na novinky, které Java 17 přináší, a zvážíme, zda je pro vás upgrade vhodný.
Řada aplikací stále využívá starší verze Javy, včetně předchozích LTS verzí, jako jsou Java 11 a Java 8.
Proč by tedy firmy měly uvažovat o přechodu na nejnovější verzi Javy? Upgrade na Java 17 s sebou nese určité úsilí, nicméně umožňuje plně využít všechny nové vlastnosti a funkce uvnitř JVM.
Mnoho společností zjednodušuje přechod na Java 17 pomocí Docker obrazů, což minimalizuje potřebné úsilí a čas. Vývojáři mohou definovat své CI/CD kanály a provozovat vše v Docker obrazech. To nijak neovlivňuje týmy, které stále pracují se staršími verzemi Javy, protože ty mohou nadále využívat stávající Docker obrazy.
Funkce v JAVA 17
Rozšířená podpora pro macOS a AArch64
Jedním z klíčových vylepšení v JVM je rozšíření podpory pro macOS na architektuře AArch64, které přináší JEP 391. Tato aktualizace přináší podporu pro nejnovější procesory (M1) od Applu, které společnost uvedla na trh v loňském roce.
Pro uživatele těchto platforem to nemusí být zásadní novinka, protože někteří dodavatelé již vydali verze JDK s podporou této architektury, dokonce i s podporou verzí Java 8. Nicméně, oficiální potvrzení podpory je zásadní pro zajištění budoucí údržby a kompatibility. Pro srovnání, podpora platformy Linux/AArch64 byla přidána v Javě 9 a Windows/AArch64 v Javě 16.
Uzavřené (sealed) třídy
Zapečetěné třídy, další novinka v Javě 17, prošly fází testování a nyní jsou oficiální součástí platformy a jazyka. Umožňují vývojářům explicitně definovat povolené podtypy, které daný typ může mít, a zabránit tak nežádoucímu rozšiřování nebo implementaci.
Díky zapečetěným třídám dokáže kompilátor generovat chyby již během kompilace, pokud se pokusíte převést nezapečetěný typ na nedovolený podtyp. Java 17 také přináší nový renderovací kanál pro AWT/Swing aplikace běžící na macOS, který využívá Apple Metal API namísto OpenGL. Kromě toho nabízí vylepšené API a funkce pro generování náhodných čísel.
Změny, odstranění a omezení v Javě 17
Java 17 přináší i několik změn, odstranění a nová omezení.
Zapouzdření vnitřních částí JDK
Jednou ze změn je posílení zapouzdření vnitřních částí JDK. Tato změna byla poprvé představena v Javě 9 a v průběhu běhu se zobrazovalo varování, když se uživatel pokusil použít reflexi, nebo podobné techniky, k obejití omezení pro používání interních API. Pro kontrolu tohoto chování byly také přidány parametry příkazové řádky.
Od Java 9 byla vyvinuta řada API, která nabízí standardizovaný způsob provádění běžných úloh. Uživatelé by měli využívat tato API namísto interních. S Javou 16 se výchozí chování změnilo z varování na zakázání přístupu a vyvolání výjimky. Stále je však možné toto chování ovlivnit pomocí parametru příkazového řádku.
V Java 17 byl parametr příkazové řádky odstraněn a již není možné toto omezení deaktivovat. Veškerý neoprávněný přístup k interním API je nyní zakázán.
Důsledná sémantika s plovoucí desetinnou čárkou
Další "odstranění" lze popsat jako obnovení důsledné sémantiky s plovoucí desetinnou čárkou. Java 1.2 zavedla změny ve výchozí sémantice pro práci s plovoucí desetinnou čárkou, které umožňovaly JVM obětovat malou míru přesnosti výpočtů pro zvýšení výkonu. Pro třídy a metody, které vyžadovaly striktní sémantiku, bylo přidáno klíčové slovo strictfp. Vzhledem k pokroku v návrhu CPU a vylepšení instrukčních sad, je nyní možné používat striktní sémantiku bez zbytečných výkonových ztrát, čímž odpadá potřeba implementovat výchozí i striktní sémantiku.
Java 17 tak odstraňuje předchozí výchozí chování a všechny operace s plovoucí desetinnou čárkou se provádějí striktně. Klíčové slovo strictfp zůstává, ale již nemá žádný vliv a vyvolává pouze varování v době kompilace.
Předběžná kompilace (AOT)
Java 9 představila experimentální funkci předběžné kompilace (AOT), která využívá kompilátor Graal. Kód JIT byl napsán v Javě. Java 10 umožnila používat kompilátor Graal jako kompilátor JIT v OpenJDK, pomocí JVMCI rozhraní. Od té doby se v této oblasti udál značný pokrok. Kompilátor Graal prošel významným vývojem a má nyní vlastní JVM pod názvem GraalVM.
Aktivace RMI
Aktivace RMI byla odstraněna v rámci JEP 407 po jejím odstranění z Java 8 a následném zamítnutí jako funkce určená k odstranění v Java 15. Aktivace RMI umožňovala distribuované objekty na vyžádání pomocí RMI, ale byla málo využívaná a v současnosti existují lepší alternativy. Ostatní části RMI nejsou tímto krokem dotčeny.
Odstranění applet API
Applet API bylo finálně určeno k odstranění v rámci JEP 398, původně bylo odstraněno v Java 9. Applet API umožňovalo integrovat Java AWT/Swing prvky do webové stránky v prohlížeči, nicméně moderní prohlížeče tuto technologii nepodporují, takže applety byly v posledních deseti letech v podstatě nedostupné.
Správce zabezpečení
Jedním z nejvýznamnějších odstranění podpory je správce zabezpečení (JEP 411). Správce zabezpečení se používá od Javy 1.0. Byl navržen k omezování možností, které může Java lokálně provádět, například omezení přístupu k síti, souborům a dalším systémovým zdrojům. Pokoušel se také izolovat nedůvěryhodný kód blokováním reflexe a specifických API.
Konec podpory správce zabezpečení započal v Javě 12. Byl přidán parametr příkazového řádku, který blokoval jeho použití za běhu. Změna provedená v Javě 17 znamená, že při pokusu o nastavení správce zabezpečení se v JVM vygeneruje varování, ať už z příkazové řádky, nebo dynamicky za běhu.
Funkce inkubátoru a náhledu
Mnoho lidí se ptalo, zda Java 17 bude obsahovat nějaké funkce náhledu a inkubátoru, vzhledem k tomu, že Java 17 byla povýšena na dlouhodobě podporovanou verzi. Java 17 má dva moduly inkubátoru a jednu funkci náhledu.
Vektorové API
Vektorové API (JEP 414) je aktuálně ve své druhé fázi inkubátoru. Toto API umožňuje vývojářům definovat vektorové výpočty, které kompilátor JIT následně převede na odpovídající vektorové instrukce, které podporuje architektura CPU, na které JVM běží (například pomocí instrukcí ze sad SSE nebo AVX).
Dříve museli vývojáři používat skalární funkce nebo vytvářet nativní knihovny specifické pro danou platformu. Implementace Vector API v Javě poskytuje také spolehlivý mechanismus zálohování, který byl v dřívějších verzích komplikovaný.
Standardizace Vector API umožňuje třídám v rámci JDK jej používat. Metody Java Arrays mismatch() by mohly být upraveny, aby byly spouštěny v Javě, a eliminovat tak nutnost údržby a psaní implementací pro různé platformy v rámci JVM.
API pro cizí funkce a paměť
Další funkce inkubátoru se nazývá Foreign Function & Memory API (JEP 412). Jedná se o evoluci a sloučení dvou dalších modulů inkubátoru z Java 16, konkrétně Foreign Linker API (JEP 389) a Foreign-Memory API (JEP 393). Obě tyto API poskytují přístup k nativní paměti a kódu za pomoci staticky typovaného programování v Javě.
Přizpůsobení vzoru pro přepínač
Poslední funkcí v náhledu v Javě 17 je přidání funkce Pattern Matching pro Switch (JEP 406). Tato jazyková funkce rozšiřuje výrazy a příkazy přepínače podle typu, podobně jako syntaxe používaná v porovnávání vzorů (JEP 394), které se stalo standardem v Java 16.
Pokud jste v minulosti chtěli provádět různé akce na základě dynamické povahy objektu, museli jste použít řetězec if-else s kontrolami typu:
String type(Object o) {
if (o instanceof List) {
return "A List of things.";
}
else if (o instanceof Map) {
return "A Map! It has keys and values.";
}
else if (o instanceof String) {
return "This is a string.";
}
else {
return "This is something else.";
}
}
Kombinací výrazu přepínače a nové funkce porovnávání vzorů pro přepínače lze tento proces zjednodušit na něco podobného:
String type(Object o) {
return switch (o) {
case List l -> "A List of things.";
case Map m -> "A Map! It has keys and values.";
case String s -> "This is a string.";
default -> "This is something else.";
};
}
Jak jste si mohli všimnout, součástí kontroly typu je deklarace proměnné. Stejně jako ostatní proměnné ve vzoru, shoda typu znamená, že tento objekt byl zkontrolován, přetypován a je dostupný z proměnné v daném rozsahu.
Funkce náhledu je dalším krokem ve vývoji porovnávání vzorů. Dalším krokem je přidání dekonstrukce polí a záznamů.
Měli byste upgradovat na Java 17?
Doporučuje se průběžně upgradovat na nejnovější verzi, ale není nutné to dělat ihned první den. Software a knihovny, které používáte, nemusí být kompatibilní s Javou 17, takže pravděpodobně budete muset nějakou dobu počkat.
Pokud stále používáte LTS verzi Javy jako Java 8 nebo Java 11, existuje mnoho důvodů pro upgrade na Java 17, a to jak v rámci jazyka, tak i JVM. Vzhledem k tomu, že se jedná o verzi s dlouhodobou údržbou, je velká šance, že i vaše produkční prostředí bude nakonec aktualizováno na Java 17.
Pokud začínáte nový projekt, nebo se připravujete na migraci projektu na Java 17, je nejefektivnější provést přechod na Java 17 co nejdříve. Minimalizujete tím náklady na budoucí migraci. Také to umožní vývojářům pracujícím na projektu využívat všechny nejnovější funkce.
Můžete využít mnoha vylepšení, která se v posledních letech objevila, jako například vylepšená podpora kontejnerů běžících na Javě a nové implementace garbage collectoru s nízkou latencí.