Noutăți și actualizări în Java 17 LTS
Pe data de 14 septembrie 2021 a fost lansată versiunea Long-Term-Support (LTS) a limbajului Java și a platformei de execuție Java 17. Vom explora noutățile aduse de această versiune și vom analiza dacă este recomandată actualizarea.
Multe aplicații încă utilizează versiuni Java mai vechi, inclusiv versiunile LTS precedente, precum Java 11 și Java 8.
Care sunt motivele pentru care companiile ar trebui să ia în considerare trecerea la cea mai recentă versiune Java? Actualizarea la Java 17 necesită un anumit efort, dar beneficiile aduse de noile caracteristici și funcționalități din interiorul JVM sunt considerabile.
Multe organizații folosesc imagini Docker pentru a facilita tranziția la Java 17, minimizând efortul și timpul necesar. Dezvoltatorii își pot defini procesele de integrare și implementare continuă (CI/CD) și le pot executa în imagini Docker, fără a afecta echipele care utilizează versiuni Java mai vechi, care pot continua să folosească imagini Docker corespunzătoare.
Funcționalități Java 17
Suport extins pentru macOS și AArch64
Un aspect esențial al acestei versiuni JVM este suportul îmbunătățit pentru macOS pe arhitectura AArch64 prin JEP 391. Acest suport vizează procesoarele din seria M1 lansate recent de Apple, oferind compatibilitate și performanță optimizată.
Deși unii furnizori au oferit anterior versiuni JDK care suportau această arhitectură, inclusiv versiuni compatibile cu Java 8, aprobarea oficială este importantă pentru a garanta întreținerea și suportul viitor al platformei. În comparație, suportul pentru Linux/AArch64 a fost introdus în Java 9, iar cel pentru Windows/AArch64 în Java 16.
Clase Sigilate
Clasele Sigilate, o caracteristică nouă în Java 17, care a trecut de faza de testare, oferă posibilitatea de a specifica subtipurile permise pentru un tip, prevenind extinderea sau implementarea neautorizată a acestuia. Această funcționalitate permite compilatorului să detecteze erori în timpul compilării, atunci când se încearcă conversia unui tip nesigilat într-un subtip nepermis.
Java 17 introduce, de asemenea, o nouă modalitate de randare pentru aplicațiile AWT/Swing pe macOS, utilizând API-ul Apple Metal în loc de OpenGL. În plus, oferă un API îmbunătățit și funcții avansate pentru generarea numerelor aleatorii.
Modificări, eliminări și limitări în Java 17
Java 17 vine cu o serie de schimbări, eliminări și noi restricții.
Încapsularea Internelor JDK
Un aspect important este finalizarea procesului de încapsulare a internelor JDK. Început în Java 9, acest proces a introdus avertismente la rulare atunci când se încerca folosirea reflecției pentru a ocoli restricțiile de utilizare a API-urilor interne. Pentru a controla acest comportament, au fost adăugate argumente de linie de comandă.
Începând cu Java 9, au fost create diverse API-uri care oferă o modalitate uniformă de a efectua cele mai frecvente sarcini, încurajând utilizarea lor internă. În Java 16, comportamentul implicit a fost schimbat de la un avertisment la dezactivarea accesului, generând o excepție. Utilizarea argumentului de linie de comandă permitea totuși modificarea acestui comportament.
În Java 17, argumentul liniei de comandă este eliminat, nefiind posibilă dezactivarea acestei restricții. Astfel, orice acces neautorizat la API-urile interne este acum strict protejat.
Semantică Strictă a Virgulă Mobilă
O altă modificare notabilă este reintroducerea semanticii întotdeauna stricte pentru virgula mobilă. În Java 1.2 s-au introdus modificări ale semanticii implicite a virgulă mobilă, permițând JVM-ului să sacrifice o mică parte din precizia calculelor cu virgulă mobilă pentru a îmbunătăți performanța. Pentru a folosi semantica strictă, s-a introdus cuvântul cheie `strictfp`. De-a lungul timpului, odată cu introducerea de noi seturi de instrucțiuni în procesoare, semantica strictă a devenit mai puțin costisitoare. Astfel, necesitatea implementării unei semantici implicite sau stricte a dispărut.
Java 17 elimină semantica implicită anterioară, toate operațiile cu virgulă mobilă fiind executate strict. Cuvântul cheie `strictfp` este păstrat, dar nu are niciun efect și generează un avertisment la compilare.
Compilarea Ahead-of-Time (AOT)
Compilarea Ahead-of-Time (AOT) a fost introdusă în Java 9 ca o caracteristică experimentală, folosind compilatorul Graal, iar codul JIT a fost scris în Java. Java 10 a făcut compilatorul Graal utilizabil ca compilator JIT în OpenJDK, prin încorporarea interfeței JVMCI. De la lansare, aceasta a adus îmbunătățiri considerabile, iar compilatorul Graal a evoluat semnificativ, fiind acum un JVM independent numit GraalVM.
Eliminarea Activării RMI
Activarea RMI a fost eliminată prin JEP 407, după ce a fost scoasă din Java 8 și, în cele din urmă, marcată ca element de eliminat în Java 15. Activarea RMI oferea o metodă de a activa resursele la cerere pentru obiecte distribuite folosind RMI. Datorită utilizării minime și existenței unor alternative mai bune, această funcționalitate a fost eliminată. Restul funcționalităților RMI nu sunt afectate.
Eliminarea API-ului Applet
API-ul Applet a fost desemnat pentru eliminare prin JEP 398, fiind inițial eliminat în Java 9. Acesta oferea o modalitate de a integra controale Java AWT/Swing într-o pagină web dintr-un browser. Din cauza lipsei de suport din partea browserelor moderne, Appleturile au devenit inaccesibile în ultimii zece ani.
Managerul de Securitate
O altă depreciere importantă este cea a Managerului de Securitate (JEP 411). Utilizat încă din Java 1.0, acest instrument era menit să limiteze acțiunile pe care Java le putea executa local, cum ar fi accesul la rețele, fișiere și alte resurse. De asemenea, încerca să izoleze codul nesigur prin blocarea reflexiei și a unor API-uri specifice.
Procesul de eliminare a Managerului de Securitate a început în Java 12, prin adăugarea unui argument de linie de comandă pentru blocarea utilizării sale. Modificarea din Java 17 face ca încercarea de a seta un Manager de Securitate, fie din linia de comandă, fie dinamic la rulare, să genereze un avertisment în JVM.
Funcții Incubator și Previzualizare
Având în vedere că Java 17 este o versiune LTS, mulți s-au întrebat dacă va include caracteristici de previzualizare și incubator. Java 17 include două module de incubator și o funcție de previzualizare!
API-ul Vector
API-ul Vector (JEP 414) se află în prezent în a doua fază a incubatorului. Acesta permite dezvoltatorilor să definească calcule vectoriale, pe care compilatorul JIT le va converti în instrucțiunile vectoriale adecvate, suportate de arhitectura CPU pe care rulează JVM-ul (de exemplu, folosind cele din seturile de instrucțiuni SSE sau AVX).
Anterior, dezvoltatorii trebuiau să folosească funcții scalare sau să creeze biblioteci native specifice platformei. Implementarea API-ului Vector în Java oferă și un mecanism de rezervă fără probleme, care era complicat în versiunile anterioare.
Standardizarea API-ului Vector permite claselor din JDK să-l utilizeze. Metodele de nepotrivire Java Arrays() ar putea fi modificate pentru a fi rulate pe Java, eliminând necesitatea de a menține și scrie multiple implementări specifice platformei în cadrul JVM.
API-ul pentru Funcții Străine și Memorie
O altă caracteristică incubator este API-ul pentru Funcții Străine și Memorie (JEP 412). Acesta este rezultatul evoluției și fuziunii a două module incubator din Java 16: API-ul Foreign Linker (JEP 389) și API-ul de memorie străină (JEP 393). Acestea oferă acces la memoria și codul nativ folosind programare de tip static scrisă în Java.
Potrivirea Pattern-ului pentru Switch
Ultima caracteristică de previzualizare a limbajului inclusă în Java 17 este Potrivirea Pattern-ului pentru Switch (JEP 406). Această funcționalitate extinde expresiile și instrucțiunile `switch` în funcție de tip, similar cu sintaxa utilizată prin potrivirea pattern-ului (JEP 394), care a devenit standard cu Java 16.
În trecut, dacă doreați să efectuați acțiuni diferite bazate pe natura dinamică a unui obiect, trebuia să construiți un lanț `if-else`, folosind verificări de instanță, ca în exemplul următor:
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."; } }
Combinând expresia `switch` cu noua funcție de potrivire a pattern-ului, codul poate fi redus la:
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."; }; }
După cum se observă, există o declarație de variabilă în procesul de verificare. Ca și în alte cazuri de potrivire a pattern-ului, verificarea de instanță indică faptul că obiectul a fost verificat și convertit corespunzător, fiind accesibil prin intermediul variabilei în zona sa de acoperire.
Funcția de previzualizare reprezintă un alt pas către potrivirea pattern-urilor. Următorul pas constă în adăugarea capacității de a deconstrui matrici și înregistrări.
Recomandări pentru Actualizarea la Java 17
Este recomandată actualizarea la cea mai recentă versiune Java, dar nu imediat după lansare. Este posibil ca software-ul și bibliotecile utilizate să nu fie încă compatibile cu Java 17, astfel încât să fie necesară o perioadă de așteptare.
Dacă utilizați o versiune LTS de Java, cum ar fi Java 8 sau Java 11, existența numeroaselor îmbunătățiri în limbaj și JVM oferă motive solide pentru actualizarea la Java 17. Fiind o versiune LTS, este foarte probabil ca mediul de producție să fie actualizat la Java 17 în viitor.
Pentru proiectele noi sau cele care se pregătesc pentru a trece la Java 17, o actualizare cât mai rapidă este cea mai eficientă opțiune, deoarece reduce costurile de migrare. În plus, permite dezvoltatorilor să utilizeze cele mai recente funcționalități și îmbunătățiri.
Astfel, se pot exploata numeroasele îmbunătățiri aduse în ultimii ani, precum suportul optimizat pentru containere care rulează pe Java, precum și implementările noi ale colectării gunoiului cu latență redusă.