Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Java 25 è una release con supporto a lungo termine (LTS), il che lo rende la scelta naturale per i team che oggi utilizzano Java 8, 11, 17 o 21. Ogni versione LTS riceve anni di aggiornamenti e correzioni della sicurezza, quindi il passaggio a Java 25 mantiene le applicazioni supportate, sicure e in grado di usare le prestazioni e i miglioramenti del linguaggio più recenti.
La domanda non è se si dovrebbe passare a una versione LTS più recente, ma quando. Più tempo si attende, più modifiche si accumulano tra la versione corrente e quella successiva supportata. Ci sono chiari vantaggi per passare a Java 25 e pianificare lo spostamento prima piuttosto che in un secondo momento riduce il rischio.
Da Java 8, ogni versione ha aggiunto funzionalità e miglioramenti. Esistono aggiunte e modifiche evidenti all'API, oltre a miglioramenti al tempo di avvio, alla velocità effettiva, all'utilizzo della memoria, alla scalabilità e alla produttività degli sviluppatori. Questo articolo evidenzia le modifiche più importanti, con particolare attenzione alle versioni Java fornite dopo la versione Java 11 LTS: Java 17, Java 21 e Java 25.
Transizione a Java 25
È possibile passare a Java 25 in modo passo per passo. Il codice sviluppato e compilato con un JDK precedente può in genere essere eseguito in Java 25 senza ricompilare. Come per qualsiasi aggiornamento principale, controllare le API rimosse, i pacchetti deprecati, l'uso di API interne e le modifiche al comportamento predefinito, in particolare per quanto riguarda garbage collection.
Se si proviene da Java 8 o 11, iniziare con la transizione da Java 8 a Java 11 guida per risolvere il set più grande di modifiche di rilievo e quindi continuare con Java 17, 21 e 25. Se si utilizza già Java 17 o 21, il passaggio a Java 25 è in genere più contenuto, perché il sistema di moduli e la maggior parte delle modifiche alla piattaforma sono già stati affrontati.
Tip
Modernizzazione delle applicazioni con GitHub Copilot può aiutarti a valutare l'applicazione, pianificare l'aggiornamento e applicare automaticamente le modifiche al codice. Supporta gli aggiornamenti tra Java versioni 8, 11, 17, 21 e 25, compila e testa il progetto dopo ogni modifica e consente di correggere le modifiche del comportamento descritte più avanti in questo articolo.
Tip
I flag JVM ottimizzati per un JDK meno recente possono diventare deprecati, rimossi o non ottimali in Java 25. Invece di trascinarti dietro impostazioni obsolete, puoi lasciare che Azure Command Launcher for Java (jaz) applichi automaticamente flag JVM adattati alla versione del JDK e alle risorse del contenitore o della macchina virtuale. Sostituisci il comando java con jaz nello script di avvio oppure Dockerfile per ottenere i vantaggi.
Modifiche generali da Java 11
Questa sezione non enumera ogni modifica apportata a partire da Java 8. Evidenzia le modifiche che hanno il maggiore impatto sulle prestazioni, la scalabilità, la diagnostica, la produttività e la sicurezza. La maggior parte di queste funzionalità è arrivata nelle versioni Java 17, 21 e 25 e ora fanno parte della baseline LTS che si ottiene con Java 25. Ogni funzionalità annota la versione Java in cui è stata integrata.
Scalabilità con thread virtuali
I thread virtuali [1] sono thread leggeri, gestiti dalla JVM anziché dal sistema operativo, che riducono notevolmente il costo della scrittura e dell'esecuzione di applicazioni simultanee a velocità effettiva elevata. Con i thread virtuali, è possibile scrivere codice in un semplice stile di thread per richiesta e ridimensionare ancora fino a un numero elevato di operazioni simultanee, ideale per i microservizi associati a I/O e carichi di lavoro di richiesta-risposta.
I thread virtuali sono stati finalizzati in Java 21. Java 24 ha rimosso una limitazione della chiave consentendo ai thread virtuali di eseguire la sincronizzazione senza bloccare i thread del gestore telefonico [2], migliorando la scalabilità per il codice che usa synchronized blocchi.
Concorrenza strutturata e valori di ambito
I valori con ambito [3] offrono un modo sicuro ed efficiente per condividere dati non modificabili all'interno e tra thread, inclusi i thread virtuali. Si tratta di un'alternativa moderna alle variabili locali del thread che funzionano bene con il modello thread-per-task.
La concorrenza strutturata [4] considera i gruppi di attività simultanee correlate come una singola unità di lavoro, semplificando la gestione e l'annullamento degli errori. Presentata per la prima volta in anteprima in Java 21, continua a evolversi e si abbina naturalmente ai thread virtuali.
Produttività del linguaggio
Una serie di miglioramenti del linguaggio distribuiti in Java da 14 a Java 25 rendono il codice più conciso, più sicuro e più facile da leggere:
-
Le espressioni switch [5] (Java 14) consentono di
switchrestituire un valore e di usare una sintassi freccia più pulita. -
Corrispondenza di pattern per
instanceof[6] (Java 16) elimina la necessità di cast espliciti dopo una verifica del tipo. - Record [7] (Java 16) modellano i dati immutabili come contenitori trasparenti per un insieme fisso di valori, riducendo il codice boilerplate.
- Le classi sealed [8] (Java 17) consentono di controllare quali classi possono estendere o implementare un tipo.
- I blocchi di testo [9] (Java 15) semplificano i valori letterali stringa multilinea.
-
Il pattern matching per
switch[10] (Java 21) e i pattern di record [11] (Java 21) consentono di esprimere chiaramente e in modo sicuro logica condizionale complessa e la destrutturazione dei dati. - Le raccolte sequenziate [12] (Java 21) aggiungono un'API uniforme per le raccolte con un ordine di incontro definito, incluso l'accesso al primo e all'ultimo elemento.
- Variabili e modelli senza nome [13] (Java 22) consentono di contrassegnare in modo esplicito variabili e componenti di pattern inutilizzati.
- Le dichiarazioni di importazione del modulo [14] (Java 25) consentono di importare i pacchetti esportati di un intero modulo con una singola dichiarazione.
- Compattare i file di origine e i metodi principali dell'istanza [15] (Java 25) riducono la cerimonia necessaria per piccoli programmi, che rende Java più facile da imparare e velocizzare il prototipo.
-
I corpi dei costruttori flessibili [16] (Java 25) consentono di eseguire istruzioni prima di chiamare
super(...)othis(...), migliorando la convalida e l'inizializzazione.
Prestazioni e avvio
Diverse modifiche di runtime migliorano la velocità effettiva, il footprint della memoria e il tempo di avvio:
- Intestazioni compatte degli oggetti [17] (Java 25) riducono le dimensioni delle intestazioni degli oggetti su piattaforme a 64 bit. Questa riduzione riduce l'uso dell'heap e può migliorare le prestazioni nei carichi di lavoro con molte allocazioni.
- La condivisione dei dati delle classi riduce il tempo di avvio eseguendo il mapping della memoria delle classi archiviate in fase di esecuzione. Gli archivi CDS predefiniti [18] (Java 12) e gli archivi CDS dinamici [19] (Java 13) semplificano l'adozione di questa funzionalità senza esecuzioni di training manuali.
- Caricamento e collegamento di classi in anticipo [20] (Java 24), insieme all'ergonomicità della riga di comando in anticipo [21] (Java 25) e alla profilatura dei metodi in anticipo [22] (Java 25), ridurre il tempo di avvio e riscaldamento riutilizzando il lavoro acquisito in un archivio applicazioni. Queste funzionalità rientrano nell’impegno di Project Leyden per ridurre i tempi di avvio di Java.
Questi miglioramenti sono particolarmente utili per i carichi di lavoro nativi del cloud e serverless, in cui l'avvio rapido e un footprint ridotto si traducono direttamente in scalabilità migliore e costi inferiori.
Raccolta dei rifiuti
Java 25 viene fornito con garbage collector maturi e con pause ridotte, adatti a un'ampia gamma di carichi di lavoro:
- ZGC [23] (Java 15) e Shenandoah [24] (Java 15) sono agenti di raccolta pronti per la produzione progettati per periodi di pausa ridotti su heap di grandi dimensioni.
- G1GC rimane l'agente di raccolta predefinito e continua a ricevere miglioramenti, inclusa l'aggiunta dell'area [25] (Java 22) per un'interazione più fluida con il codice nativo.
- ZGC generazionale [26] (Java 21) migliora l'efficienza mantenendo generazioni separate. A partire da Java 23, ZGC viene eseguito in modalità di generazione per impostazione predefinita [27]e la modalità non generazionale è stata rimossa in Java 24.
- Shenandoah generazionale [28] (Java 25) aggiunge una modalità generazionale all'agente di raccolta Shenandoah per una maggiore velocità effettiva e resilienza sotto pressione di memoria.
JVM imposta le impostazioni predefinite di GC per il caso d'uso medio. Ottimizzare queste impostazioni predefinite e altre impostazioni GC per ottimizzare la velocità effettiva o la latenza in base ai requisiti dell'applicazione.
Tip
Il Garbage Collector predefinito e molte impostazioni predefinite di JVM differiscono tra le versioni di Java, quindi le impostazioni ottimizzate per Java 8 o 11 potrebbero non essere più ottimali in Java 25. L'utilità di avvio dei comandi Azure per Java (jaz) legge automaticamente i limiti di memoria e CPU del contenitore e applica i flag JVM personalizzati alla versione e all'ambiente JDK.
Diagnostica e osservabilità
La diagnostica è stata migliorata nelle versioni, sia nel linguaggio che in Java Flight Recorder (JFR):
-
Utili NullPointerExceptions [29] (Java 14) descrivono esattamente quale variabile era
null, che accelera il debug. - Il flusso di eventi JFR [30] (Java 14) consente agli strumenti di utilizzare i dati di profilatura e diagnostica in modo continuo anziché da un file di dump.
- Profilazione del tempo CPU con JFR [31] (Java 25) aggiunge la profilazione sperimentale dei metodi basata sul tempo CPU su Linux.
- Il campionamento cooperativo JFR [32] (Java 25) migliora la stabilità del campionamento dello stack.
- Misurazione dei tempi e tracciamento dei metodi con JFR [33] (Java 25) consente di misurare i tempi e tracciare metodi specifici senza modificare il codice dell'applicazione.
Sicurezza e crittografia
Java 25 rafforza il profilo di sicurezza della piattaforma, compresa la preparazione per un mondo post-quantistico:
- Edwards-Curve Digital Signature Algorithm (EdDSA) [34] (Java 15) aggiunge uno schema di firma moderno e ad alte prestazioni.
- L'API Key Encapsulation Mechanism [35] (Java 21) fornisce un'API standard per gli algoritmi KEM.
- La crittografia resistente al quantum aggiunge implementazioni standard del meccanismo di incapsulamento delle chiavi basate su reticolo del modulo (ML-KEM) [36] (Java 24) e dell'algoritmo di firma digitale (ML-DSA) [37] (Java 24).
- L'API della funzione di derivazione chiave [38] (Java 25) fornisce un'API standard per le funzioni di derivazione delle chiavi.
Interoperabilità nativa
L'API Foreign Function and Memory [39] (Java 22) offre un modo sicuro, efficiente e puro Java per chiamare librerie native e accedere alla memoria nativa. È una sostituzione moderna per la Java Native Interface (JNI) che riduce boilerplate e migliora la sicurezza.
Strumenti e librerie
Diverse aggiunte migliorano lo sviluppo quotidiano e riducono la necessità di strumenti di terze parti:
-
Lo strumento di creazione di pacchetti () [
jpackage40] (Java 16) crea programmi di installazione e pacchetti nativi per le applicazioni Java. - Simple Web Server [41] (Java 18) fornisce un server HTTP statico-file minimo per la creazione di prototipi e test.
- I generatori di numeri pseudorandomi avanzati [42] (Java 17) aggiungono nuove interfacce e implementazioni per la generazione di numeri casuali.
Cambiamenti nel comportamento da prevedere
Alcune modifiche apportate dopo Java 11 modificano il comportamento predefinito, quindi esaminarle prima dell'aggiornamento:
-
Incapsulare fortemente gli elementi interni del JDK [43] (Java 17) blocca per impostazione predefinita l'accesso riflessivo alla maggior parte delle API interne. Il codice o le librerie che raggiungono
sun.*o altri pacchetti interni potrebbero richiedere aggiornamenti. - UTF-8 per impostazione predefinita [44] (Java 18) rende UTF-8 il charset predefinito per le API standard Java. Le applicazioni basate su un set di caratteri predefinito specifico della piattaforma potrebbero comportarsi in modo diverso.
-
Dichiarare obsoleta la finalizzazione per la rimozione [45] (Java 18) indica che
finalize()sarà infine rimossa. Eseguire la migrazione atry-with-resources ojava.lang.ref.Cleaner. - Prepararsi a impedire il caricamento dinamico degli agenti [46] (Java 21) avvisa quando un agente viene caricato in una JVM in esecuzione. Alcuni strumenti di monitoraggio e strumentazione potrebbero richiedere modifiche alla configurazione.
Tip
Modernizzazione delle app con GitHub Copilot può aiutarti a valutare e risolvere automaticamente questi cambiamenti di comportamento quando esegui l'aggiornamento.
Contenitori e cloud
La consapevolezza dei contenitori di JVM, introdotta per Docker e altri runtime di contenitori, continua a migliorare. La JVM legge i vincoli di CPU e memoria impostati dai gruppi di controllo del contenitore (cgroup) e ridimensiona l'heap e altre risorse di conseguenza. In combinazione con l'avvio più veloce, un footprint inferiore e i thread virtuali, Java 25 è particolarmente adatto alle distribuzioni in contenitori e serverless in Azure.
Se si eseguono carichi di lavoro Java in contenitori Azure o macchine virtuali, l'utilità di avvio dei comandi di Azure per Java (jaz) può applicare automaticamente impostazioni predefinite JVM ottimizzate per il cloud.
Passaggi successivi
- Transizione da Java 8 a Java 11
- Motivi per passare a Java 11 e oltre
- Utilità di avvio comandi Azure per Java
References
[1] Oracle Corporation, "JEP 444: Virtual Threads". (Online). Disponibile: https://openjdk.org/jeps/444.
[2] Oracle Corporation, "JEP 491: Sincronizzare i thread virtuali senza pinning." (Online). Disponibile: https://openjdk.org/jeps/491.
[3] Oracle Corporation, "JEP 506: Valori con ambito". (Online). Disponibile: https://openjdk.org/jeps/506.
[4] Oracle Corporation, "JEP 453: Concorrenza strutturata (anteprima)." (Online). Disponibile: https://openjdk.org/jeps/453.
[5] Oracle Corporation, "JEP 361: Switch Expressions". (Online). Disponibile: https://openjdk.org/jeps/361.
[6] Oracle Corporation, "JEP 394: Pattern Matching for instanceof". (Online). Disponibile: https://openjdk.org/jeps/394.
[7] Oracle Corporation, "JEP 395: Records". (Online). Disponibile: https://openjdk.org/jeps/395.
[8] Oracle Corporation, "JEP 409: classi sigillate". (Online). Disponibile: https://openjdk.org/jeps/409.
[9] Oracle Corporation, "JEP 378: Blocchi di testo". (Online). Disponibile: https://openjdk.org/jeps/378.
[10] Oracle Corporation, "JEP 441: Criteri di ricerca per l'opzione". (Online). Disponibile: https://openjdk.org/jeps/441.
[11] Oracle Corporation, "JEP 440: Record Patterns". (Online). Disponibile: https://openjdk.org/jeps/440.
Oracle Corporation, "JEP 431: Raccolte sequenziate". (Online). Disponibile: https://openjdk.org/jeps/431.
[13] Oracle Corporation, "JEP 456: Variabili e modelli senza nome". (Online). Disponibile: https://openjdk.org/jeps/456.
[14] Oracle Corporation, "JEP 511: Dichiarazioni di importazione dei moduli". (Online). Disponibile: https://openjdk.org/jeps/511.
[15] Oracle Corporation, "JEP 512: Compact Source Files and Instance Main Methods." (Online). Disponibile: https://openjdk.org/jeps/512.
[16] Oracle Corporation, "JEP 513: Corpi flessibili dei costruttori." (Online). Disponibile: https://openjdk.org/jeps/513.
[17] Oracle Corporation, "JEP 519: Compact Object Headers." (Online). Disponibile: https://openjdk.org/jeps/519.
[18] Oracle Corporation, "JEP 341: Archivi CDS predefiniti". (Online). Disponibile: https://openjdk.org/jeps/341.
[19] Oracle Corporation, "JEP 350: Dynamic CDS Archives." (Online). Disponibile: https://openjdk.org/jeps/350.
Oracle Corporation, "JEP 483: Ahead-of-Time Class Loading & Linking". (Online). Disponibile: https://openjdk.org/jeps/483.
Oracle Corporation , "JEP 514: Ahead-of-Time Command-Line Ergonomics". (Online). Disponibile: https://openjdk.org/jeps/514.
[22] Oracle Corporation, "JEP 515: Profilazione anticipata dei metodi." (Online). Disponibile: https://openjdk.org/jeps/515.
[23] Oracle Corporation, "JEP 377: ZGC: un garbage collector scalabile a bassa latenza." (Online). Disponibile: https://openjdk.org/jeps/377.
Oracle Corporation , "JEP 379: Shenandoah: A Low-Pause-Time Garbage Collector". (Online). Disponibile: https://openjdk.org/jeps/379.
[25] Oracle Corporation, "JEP 423: Blocco delle regioni per G1." (Online). Disponibile: https://openjdk.org/jeps/423.
[26] Oracle Corporation, "JEP 439: Generational ZGC." (Online). Disponibile: https://openjdk.org/jeps/439.
[27] Oracle Corporation, "JEP 474: ZGC: Modalità generazionale per impostazione predefinita." (Online). Disponibile: https://openjdk.org/jeps/474.
[28] Oracle Corporation, "JEP 521: Generational Shenandoah." (Online). Disponibile: https://openjdk.org/jeps/521.
[29] Oracle Corporation, "JEP 358: Helpful NullPointerExceptions." (Online). Disponibile: https://openjdk.org/jeps/358.
[30] Oracle Corporation, "JEP 349: JFR Event Streaming". (Online). Disponibile: https://openjdk.org/jeps/349.
[31] Oracle Corporation, "JEP 509: JFR CPU-Time Profiling (Sperimentale)." (Online). Disponibile: https://openjdk.org/jeps/509.
[32] Oracle Corporation, "JEP 518: Campionamento cooperativo JFR." (online). Disponibile: https://openjdk.org/jeps/518.
Oracle Corporation, "JEP 520: JFR Method Timing & Tracing". (Online). Disponibile: https://openjdk.org/jeps/520.
[34] Oracle Corporation, "JEP 339: Edwards-Curve Digital Signature Algorithm (EdDSA)." (Online). Disponibile: https://openjdk.org/jeps/339.
[35] Oracle Corporation, "JEP 452: API del meccanismo di incapsulamento delle chiavi." (Online). Disponibile: https://openjdk.org/jeps/452.
[36] Oracle Corporation, "JEP 496: meccanismo di incapsulamento delle chiavi basato su reticoli modulari resistente ai quanti." (online). Disponibile: https://openjdk.org/jeps/496.
[37] Oracle Corporation, "JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm." (Online). Disponibile: https://openjdk.org/jeps/497.
[38] Oracle Corporation, "JEP 510: API per la funzione di derivazione delle chiavi." (Online). Disponibile: https://openjdk.org/jeps/510.
[39] Oracle Corporation, "JEP 454: Foreign Function & Memory API". (Online). Disponibile: https://openjdk.org/jeps/454.
[40] Oracle Corporation, "JEP 392: Packaging Tool". (Online). Disponibile: https://openjdk.org/jeps/392.
[41] Oracle Corporation, "JEP 408: Simple Web Server". (Online). Disponibile: https://openjdk.org/jeps/408.
[42] Oracle Corporation, "JEP 356: generatori di numeri pseudocasuali migliorati." (online). Disponibile: https://openjdk.org/jeps/356.
[43] Oracle Corporation, "JEP 403: Incapsulare fortemente gli elementi interni del JDK." (Online). Disponibile: https://openjdk.org/jeps/403.
[44] Oracle Corporation, "JEP 400: UTF-8 per impostazione predefinita". (Online). Disponibile: https://openjdk.org/jeps/400.
[45] Oracle Corporation, "JEP 421: Deprecare la finalizzazione in vista della rimozione." (Online). Disponibile: https://openjdk.org/jeps/421.
[46] Oracle Corporation, "JEP 451: Prepare to Disallow the Dynamic Loading of Agents." (Online). Disponibile: https://openjdk.org/jeps/451.