Dopo sei mesi di sviluppo, Oracle ha pubblicato la piattaforma Java SE 25 (Java Platform, Standard Edition 25), utilizzando il progetto open source OpenJDK come implementazione di riferimento. Fatta eccezione per la rimozione di alcune funzionalità deprecate, Java SE 25 mantiene la compatibilità con le versioni precedenti della piattaforma Java: la maggior parte dei progetti Java precedentemente scritti funzionerà senza modifiche con la nuova versione. Le build pronte per l'installazione di Java SE 25 (JDK, JRE e Server JRE) sono disponibili per Linux (x86_64, AArch64), Windows (x86_64) e macOS (x86_64, AArch64). L'implementazione di riferimento di Java SE 25, sviluppata nell'ambito del progetto OpenJDK, è completamente open source sotto la licenza GPLv2 con eccezioni GNU ClassPath che consentono il linking dinamico con prodotti commerciali.
Java SE 25 è incluso nelle versioni con supporto a lungo termine, con aggiornamenti disponibili fino al 2033 (gli aggiornamenti pubblici saranno disponibili fino a settembre 2030). Le versioni Java SE 17 e 21 continuano ad essere supportate come LTS, con aggiornamenti previsti fino al 2029 e 2031, rispettivamente (gli aggiornamenti pubblici fino al 2026 e 2028). Il supporto esteso per le versioni LTS di Java SE 8 e 11 sarà disponibile fino al 2030 e 2032.
Tra le novità proposte in Java SE 25 (1, 2, 3, 4):
- È stato aggiunto un API sperimentale StableValue per lavorare con oggetti contenenti dati immutabili e trattati nella JVM come costanti. A tali oggetti vengono applicate ottimizzazioni delle prestazioni simili ai campi contrassegnati con la parola chiave «final». L'API StableValue separa la creazione di valori permanenti dalla loro inizializzazione, garantisce che il valore possa essere inizializzato solo una volta, riduce i tempi di avvio delle applicazioni e consente di applicare nel codice utente ottimizzazioni di piegatura delle costanti (constant-folding), utilizzate in precedenza solo nel codice interno del JDK. class Application { // Era: // static final UserService USERS = new UserService(); // È diventato: static final StableValue USERS = StableValue.of(); public static UserService users() { return USERS.orElseSet(UserService::new); } }
- È stato aggiunto un API sperimentale per la codifica e decodifica di oggetti contenenti chiavi crittografiche, certificati e elenchi di certificati revocati, utilizzando il formato PEM (Privacy-Enhanced Mail).
- È stato aggiunto il supporto per i valori scope (Scoped Values), che consentono di condividere dati immutabili nei flussi e di scambiare dati in modo efficiente tra flussi secondari (i valori sono ereditati). I Scoped Values si stanno sviluppando per sostituire il meccanismo delle variabili locali al flusso (thread-local variables) e sono più efficienti quando si utilizzano un numero molto elevato di flussi virtuali (migliaia e milioni di flussi). La principale differenza tra i Scoped Values e le variabili locali al flusso è che i primi vengono scritti una sola volta, non possono essere modificati ed rimangono disponibili solo durante l'esecuzione del flusso.
- È stata aggiunta un'API per utilizzare funzioni crittografiche di derivazione delle chiavi (KDF, key derivation function), che consentono di generare ulteriori chiavi di lunghezza necessaria a partire da una chiave segreta (ad esempio, una password) e da un insieme di dati arbitrario.
- Il codice e gli script di build per supportare i sistemi a 32 bit x86 sono stati rimossi. La cessazione del supporto per i sistemi x86 a 32 bit ha semplificato l'infrastruttura per la costruzione e il test di JDK, e ha anche reso possibile implementare funzionalità legate a piattaforme senza dover creare gestori di fallback per i sistemi a 32 bit x86.
- È stata aggiunta la possibilità di utilizzare l'espressione «import module M» per importare immediatamente tutti i pacchetti esportati dal modulo specificato. Questa modifica semplifica notevolmente il riutilizzo delle librerie modulari, consentendo l'inclusione di librerie e classi senza dover definire la loro posizione nella gerarchia dei pacchetti. Ad esempio, specificando «import module java.base» si importeranno tutti i 54 pacchetti contenuti nel modulo java.base, che in precedenza avrebbero dovuto essere menzionati singolarmente («import java.io.*», «import java.util.*» e così via).
- È stata proposta una versione compatta della sintassi dei programmi, che può risultare utile per l'apprendimento e lo sviluppo di piccole applicazioni. In questa forma compatta non è necessario definire classi aggiuntive, vengono importati automaticamente API standard e sono disponibili metodi semplificati per l'input/output. Ad esempio, l'applicazione «Hello, World!» può essere ridotta a: void main() { IO.println("Hello, World!"); }
- È consentito indicare espressioni nei costruttori prima della chiamata a super(...), utilizzata per esplicitamente invocare il costruttore della classe genitore dal costruttore della classe derivata, se queste espressioni non fanno riferimento all'istanza creata dal costruttore. class Outer { void hello() { System.out.println("Hello"); } class Inner { Inner() { hello(); super(); } } }
- È stata aggiunta una modalità generativa per il garbage collector Shenandoah, che gestisce separatamente gli oggetti vecchi e quelli appena creati per migliorare l'efficienza della pulizia degli oggetti a breve termine. Questa nuova modalità offre una capacità di elaborazione più prevedibile, una maggiore resilienza alle variazioni di carico e una riduzione del consumo di memoria durante la raccolta dei rifiuti. Il pianificatore di Shenandoah mira a ridurre i tempi di arresto durante la raccolta dei rifiuti eseguendo un volume maggiore di lavoro in parallelo con l'esecuzione delle applicazioni Java.
- È stata semplificata la creazione della cache per il caricamento e la composizione delle classi anticipato (Ahead-of-Time), il che permette di accelerare l'avvio della JVM HotSpot utilizzando classi già caricate e compilate. Durante l'avvio non sono più necessarie operazioni separate per registrare l'attività e creare la cache, ma è sufficiente un solo comando: java -XX:AOTCacheOutput=app.aot -cp app.jar com.example.App ...
- All'avvio, HotSpot Java VM consente l'uso dei profili di esecuzione dei metodi ottenuti durante l'ultima esecuzione dell'applicazione. Questa modifica consente al JIT compiler di evitare la raccolta di statistiche e di iniziare immediatamente a generare codice nativo senza attendere la formazione del profilo.
- HotSpot JVM supporta intestazioni degli oggetti compatte, la cui dimensione è stata ridotta da 96 a 64 bit (da 12 a 8 byte) nei sistemi a 64 bit. La riduzione delle dimensioni delle intestazioni consente di ridurre la dimensione dell'heap e di aumentare l'efficienza della cache.
- È stata proposta un'implementazione di prova dell'API Vector, che fornisce funzioni per calcoli vettoriali eseguiti utilizzando le istruzioni vettoriali dei processori x86_64 e AArch64, permettendo di applicare operazioni contemporaneamente a più valori (SIMD). A differenza delle capacità di auto-vettorizzazione delle operazioni scalari fornite dal JIT compiler di HotSpot, la nuova API consente di gestire esplicitamente la vettorizzazione per l'elaborazione parallela dei dati.
- Proposto per il test un quinto prototipo preliminare dell'API per la concorrenza strutturata, che semplifica lo sviluppo di applicazioni multithread gestendo più attività eseguite in thread diversi come un'unica unità.
- Nel meccanismo di matching è stata proposta una terza bozza per l'utilizzo dei tipi primitivi (int, byte, char e altri tipi base che non sono oggetti) in tutti i tipi di template, nell'operatore «instanceof» e nei blocchi «switch». switch (x.getStatus()) { case 0 -> «ok»; case 1 -> «avviso»; case 2 -> «errore»; case int i -> «stato sconosciuto: » + i; } if (i instanceof byte b) { … b … }
- Nel JDK Flight Recorder (JFR) è stata aggiunta una funzionalità sperimentale per il profilo con un tracciamento più preciso del consumo delle risorse CPU sulla piattaforma Linux. Le informazioni sui tempi di esecuzione di diverse costruzioni possono essere visualizzate in modo chiaro utilizzando grafici a colori «FlameGraph».
- È stata aumentata la stabilità del JDK Flight Recorder (JFR) durante il campionamento asincrono degli stack dei thread Java, evitando di passare per lo stack delle chiamate solo in «punti sicuri» (safepoints).
- In JDK Flight Recorder (JFR) sono stati aggiunti strumenti per il tracciamento e la valutazione dei tempi di esecuzione dei metodi. È supportato il tracciamento dello stack delle chiamate per metodi specifici e la registrazione di statistiche precise sulle chiamate ai metodi, coprendo metriche come il tempo di esecuzione e il numero di chiamate.
Fonte: opennet.ru
