Vad är nytt i Java 17?

Long-Term-Support-versionen (LTS) av Java-språk- och runtime-plattformen Java 17 lanserades den 14 september 2021. Låt oss lära oss vad som är nytt i Java 17 och om du bör uppgradera.

Många applikationer använder äldre versioner av Java, inklusive de tidigare LTS-versionerna av Java: Java 11 och Java 8.

Varför ska företag uppgradera till den senaste Java-versionen? Uppgraderingen till Java 17 kräver ansträngning, främst för att få ut det mesta av de nya funktionerna i JVM.

Många företag använder Docker- och Docker-bilder för att enkelt byta till Java 17 med minimal ansträngning och tid. Utvecklare kan definiera sina pipelines för kontinuerlig integration/distribution (CI/CD) och köra allt i Docker-avbildningar. Detta kommer inte att påverka andra team som använder äldre Java-versioner, eftersom de kan använda gamla Docker-bilder.

JAVA 17 funktioner

Stöd för macOS och AArch64

En av de kritiska JVM-funktionerna som läggs till i den här versionen är att förbättra stödet för macOS på AArch64-arkitekturen med JEP 391. Den kommer att stödja den senaste serien av processorer (M1) som Apple släppte med sina datorer under det senaste året.

Det är inte nödvändigtvis en stor sak för användare på dessa plattformar eftersom vissa leverantörer har lanserat versioner av JDK som stöder denna arkitektur och till och med returnerar stöd från Java 8. Det officiella godkännandet är dock viktigt för att säkerställa framtida underhåll och support av plattformen. Som jämförelse har stöd för Linux/AArch64-plattformen lagts till Java 9 och Windows/AArch64 i Java 16.

Förseglade klasser

Förseglade klasser är en funktion som introducerades i Java 17. Funktionen förseglade klasser har avslutat sin testfas och har blivit en officiell plattform och språk i Java 17. Den tillåter en utvecklare att specificera de tillåtna undertyper som en typ kan ha och hindra andra från att utöka eller implementera det på ett sätt som inte är avsett.

Förseglade klasser tillåter också kompilatorn att generera fel vid kompilering när du försöker konvertera en oförseglad typ till en otillåten undertyp. Java 17 ger också en ny renderingspipeline för AWT/Swing-appar som körs på macOS med Apple Metal API istället för OpenGL. Den har ett förbättrat API och förbättrade funktioner för att generera slumptal.

Ändringar, raderingar och begränsningar i Java 17

Java 17 ger också flera ändringar, raderingar och nya begränsningar.

Inkapsling av JDK Internals

En förändring är slutsatsen av inkapslingsprocessen för JDK Internals. Första gången detta introducerades var inom Java 9 och skulle ge varningar under körning när en användare försökte använda reflektion eller liknande för att kringgå de vanliga begränsningarna för att använda interna API:er. Kommandoradsargument lades också till för att reglera detta beteende.

Från Java 9 har olika API:er skapats för att erbjuda ett enhetligt sätt att utföra de vanligaste uppgifterna; användare skulle använda dessa API:er internt. Med Java 16 ändrades standarden från en varning till att inaktivera åtkomst för att kasta ett undantag. Den använder dock kommandoradsargumentet för att ändra beteendet.

Med Java 17 elimineras kommandoradsargumentet, och det är möjligt att avaktivera denna begränsning. Detta innebär att all icke-auktoriserad åtkomst till dessa interna API:er nu är skyddad.

Alltid-strikt flytande-punkt-semantik

En ytterligare ”borttagning” kan beskrivas som återinförandet av Always-Strict Floating Point-semantik. Java 1.2 introducerade modifieringar av flyttalssemantikens standard i Java som gör att JVM kan handla med en liten mängd precision i flyttalsberäkningar för att förbättra prestandan. I klasser och metoder där strikt semantik måste användas lades ett strictfp nyckelord till. Sedan dess har olika typer av instruktionsuppsättningar introducerats till processorerna, vilket gör att strikt flyttalssemantik kan användas utan onödiga kostnader. Behovet av att implementera en standard eller strikt semantik har eliminerats.

Java 17 tar bort den tidigare standardsemantiken och alla flyttalsoperationer exekveras strikt. Termen strictfpis finns fortfarande kvar. Det har dock ingen effekt och orsakar en varning vid kompileringstillfället.

Ahead-of-Time (AOT) sammanställning

Java 9 introducerade ahead-of-time (AOT) kompilering som en experimentell funktion som använder Graal-kompilatorn, och en JIT-kod skrevs med Java. Java 10 gjorde Graal-kompilatorn användbar som en JIT-kompilator i OpenJDK genom att införliva JVMCI-gränssnittet. Sedan den släpptes har den varit en enorm förbättring. Graal-kompilatorn har sett enorma framsteg och har sin JVM under namnet GraalVM.

RMI-aktivering

RMI-aktivering eliminerades i JEP 407 efter borttagningen från Java 8 och slutligen utfasad och markerad som ett krav för borttagning inom Java 15. RMI-aktivering tillhandahöll en metod för att aktivera distribuerade objekt on-demand-resurser med RMI. Den användes dock minimalt och ett bättre alternativ finns tillgängligt idag. Resten av RMI påverkas inte av elimineringen av aktiveringsdelen.

Borttagning av Applet API

Applet API har äntligen utsetts för borttagning av JEP 398, som ursprungligen togs bort inom Java 9. Applet API gav ett sätt att integrera Java AWT/Swing-kontroller på en webbsida i en webbläsare. Men ingen modern webbläsare kan stödja detta, vilket betyder att applets har varit i princip otillgängliga under det senaste decenniet eller så.

Säkerhets chef

Den mest avgörande avskrivningen är att det är säkerhetschefen ( JEP 411). Security Manager har använts ett tag sedan Java 1.0. Den var utformad för att begränsa vad Java kunde göra lokalt på maskinen, som att begränsa åtkomsten till nätverk, filer och andra nätverksresurser. Den försöker också sandboxa kod som inte är betrodd genom att blockera reflektionen och specifika API:er.

Slutet på Security Manager startade i Java 12. Ett kommandoradsargument lades till för att blockera användningen av säkerhetshanteraren vid körning. Ändringen som görs i Java 17 innebär att en runtime-varning genereras i JVM när man försöker ställa in en Security Manager, antingen från kommandoraden eller dynamiskt under runtime.

Inkubator och förhandsvisningsfunktioner

Många undrade om Java 17 skulle ha några förhandsgransknings- och inkubatorfunktioner, med tanke på att Java 17 marknadsfördes till att vara en långtidsstödd version. Java 17 har två inkubatormoduler och en förhandsvisningsfunktion!

Vektor API

Vector API ( JEP 414) är för närvarande i sin andra fas av inkubatorn. API:et tillåter utvecklare att definiera vektorberäkningar som JIT-kompilatorn sedan kommer att konvertera till lämplig vektorinstruktion som stöds av CPU-arkitekturen som JVM körs på (till exempel med användning av SSE- eller AVX-instruktionsuppsättningarna).

Tidigare var utvecklare tvungna att använda skalära funktioner eller bygga inbyggda bibliotek som var specifika för plattformen. Implementering av Vector API i Java ger också en sömlös reservmekanism som var komplicerad i tidigare versioner.

Standardiseringen av Vector API gör det möjligt för klasserna inom JDK att använda det. Java Arrays mismatch()-metoder kan ändras för att köras på Java istället, vilket eliminerar kravet på att underhålla och skriva flera plattformsspecifika implementeringar inom JVM.

Foreign Function & Memory API

En extra inkubatorfunktion kallas Foreign Function & Memory API ( JEP 412). Det är en utveckling och sammanslagning av två andra inkubatormoduler av Java 16 som är The Foreign Linker API ( JEP 389) och Foreign-Memory API ( JEP 393). Båda ger tillgång till inbyggt minne och kod genom att använda statiskt typad programmering skriven i Java.

Mönstermatchning för Switch

Den sista funktionen i språkförhandsvisningen som ingår i Java 17 är inkluderingen av Pattern Matching for Switch ( JEP 406). Denna språkfunktion utökar switchuttrycken och -satserna efter typ, liknande syntaxen som används genom Pattern Matching (JEP 394), som blev standard med Java 16.

Tidigare, om du ville utföra olika åtgärder baserat på ett objekts dynamiska natur, skulle du behöva konstruera en om-annas-kedja med hjälp av en instans av kontroller som:

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.";
  }
}

Genom att kombinera switch-uttrycket samt den nya mönstermatchningsfunktionen för switchar kan processen reduceras till något som liknar:

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.";
  };
}

Som du kanske har märkt finns deklarationen av en variabel under kontroll. Liksom de andra variablerna i Pattern indikerar matchningen av instans att detta objekt typkontrollerades och castades och är tillgängligt från variabeln inom dess aktuella område.

Förhandsgranskningsfunktionen är ytterligare ett steg mot mönstermatchning. Nästa steg är att inkludera förmågan att dekonstruera arrayer och poster.

Ska du uppgradera till Java 17?

Ja, du måste hela tiden uppgradera till den senaste versionen, dock inte så snart som första dagen. Programvaran och biblioteken du använder kanske inte har uppdaterats för att inkludera kompatibilitet med Java 17, så du kan behöva vänta ett tag tills det är klart.

Om du har fastnat för en LTS-version av Java som Java 8 eller Java 11, finns det många alternativ inom språket och inom själva JVM som kräver en uppgradering upp till Java 17. Eftersom det är en långsiktig underhållsversion finns det en stor chans att din produktionsmiljö så småningom kommer att uppdateras till Java 17 också.

Om du börjar ett helt nytt projekt, eller håller på att göra ditt projekt klart och redo för Java 17, är det förmodligen det mest effektiva valet att byta till Java 17 förr snarare än senare eftersom det minskar kostnaderna för att flytta. Detta gör det också möjligt för utvecklarna som arbetar med projektet att använda alla de senaste funktionerna och ops-sidan.

Du kan dra nytta av de många förbättringar som har skett under de senaste åren, såsom förbättrat stöd för behållare som körs på Java, såväl som nya implementeringar av skräpsamlare med låg latens.