Java 25: Tutte le novità del nuovo LTS release in arrivo a settembre 2025
Il prossimo Java 25, atteso il 16 settembre 2025 come nuova release Long-Term Support (LTS), rappresenta un passaggio importante per l’ecosistema. Si tratta di un aggiornamento che porta novità a più livelli: linguaggio, API, runtime e strumenti di diagnostica.
L’obiettivo è duplice: modernizzare l’esperienza di sviluppo e ottimizzare le performance delle applicazioni in scenari enterprise, cloud-native e distribuiti.
Novità del linguaggio e del compilatore
Con Java 25 il linguaggio fa un ulteriore passo avanti verso espressività e semplicità, riducendo la verbosità tipica di Java e introducendo costrutti che avvicinano l’esperienza d’uso a quella di linguaggi moderni, senza però sacrificare la solidità e la compatibilità retroattiva che lo hanno sempre contraddistinto.
- Pattern matching esteso ai tipi primitivi (JEP 507 – Third Preview)
Dopo essere stato esteso a classi, record e sealed types, il pattern matching ora copre anche i tipi primitivi (int, double, ecc.). Questo significa che espressioni comuni come controlli su instanceof o switch diventano più concise e leggibili.
Il beneficio è duplice: da un lato si elimina boilerplate legato al casting esplicito, dall’altro si ottiene un linguaggio più coerente, in cui i pattern diventano uno strumento unificato per gestire qualsiasi tipo di dato.
- Module Import Declarations (JEP 511 – Preview)
Una delle novità più discusse è l’introduzione delle dichiarazioni di importazione a livello di modulo.
Tradizionalmente, le dipendenze venivano specificate esclusivamente nel file module-info.java tramite la keyword requires. Con Java 25 sarà possibile utilizzare import module direttamente nei sorgenti, affiancandolo agli import tradizionali delle classi.
Questa innovazione porta maggiore leggibilità e immediatezza: chi legge un file può capire subito quali moduli esterni vengono utilizzati. Inoltre, strumenti come IDE e analizzatori statici potranno inferire in modo più accurato le dipendenze reali.
Va però usata con attenzione: in caso di classi con lo stesso nome presenti in moduli diversi (ad esempio Date in java.util e java.sql), l’ambiguità va risolta con import più specifici.
- Compact Source Files e Instance Main Methods (JEP 512)
Con Java 25 arriva una semplificazione molto attesa: i compact source files, che permettono di scrivere programmi senza dichiarare una classe.
Questa feature riduce la barriera iniziale per chi si avvicina al linguaggio: è ora possibile scrivere un semplice main senza dover incapsulare tutto in una classe pubblica. È un approccio che rende Java più accessibile in contesti didattici, prototipazione rapida o scripting.
Pur non sostituendo il modello classico, questa possibilità rappresenta un ponte tra il rigore della piattaforma e le esigenze di agilità degli sviluppatori moderni.
- Flexible Constructor Bodies (JEP 513 – Final)
Un’altra modifica significativa riguarda la gestione dei costruttori. In precedenza, Java imponeva che la chiamata a super() o this() fosse la prima istruzione. Ciò spesso costringeva a duplicare logiche di validazione o a ricorrere a metodi statici ausiliari.
Con Java 25 questa rigidità viene meno: ora è possibile eseguire controlli o inizializzazioni prima della chiamata al costruttore della superclasse.
Il risultato è una maggiore chiarezza e sicurezza: validazioni sugli argomenti possono avvenire in modo naturale, mantenendo il costruttore come luogo principale per l’integrità dell’oggetto, senza ricorrere a workaround.
Queste novità seguono una direzione ben precisa:
- Abbassare la barriera d’ingresso per i nuovi sviluppatori, grazie a file sorgente più semplici e costrutti più intuitivi.
- Aumentare la produttività per chi già conosce bene la piattaforma, con pattern uniformi, import più espressivi e costruttori meno vincolanti.
- Favorire la leggibilità e la manutenzione del codice in team, un aspetto chiave nei contesti enterprise dove Java continua a essere il linguaggio predominante.
API e runtime
Con Java 25 si consolida un percorso già avviato nelle release precedenti: rendere la piattaforma più efficiente, sicura e adatta ai workload moderni, in particolare quelli distribuiti e ad alta concorrenza. Le novità si concentrano su tre assi principali: gestione della concorrenza, sicurezza e crittografia, ottimizzazione delle performance.
- Scoped Values (JEP 506 – Final)
Gli Scoped Values introducono un’alternativa più leggera e sicura a ThreadLocal.
Mentre ThreadLocal permette di associare dati al ciclo di vita di un thread, con il rischio di memory leak e complessità nella gestione, gli Scoped Values offrono binding immutabili e limitati a uno scope definito. Questo approccio si integra perfettamente con le Virtual Threads (introdotte in Java 21 e ora mature), rendendo più semplice passare contesti — come informazioni sull’utente o parametri di sicurezza — lungo una catena di chiamate.
Il risultato è una riduzione del rischio di bug legati alla concorrenza e un miglior controllo del ciclo di vita delle variabili di contesto.
- Structured Concurrency (JEP 505 – Fifth Preview)
Con il modello di Structured Concurrency, i task concorrenti correlati vengono trattati come un’unica unità logica. In pratica, anziché gestire manualmente thread e pool, gli sviluppatori possono ragionare in termini di “operazioni correlate” che iniziano e finiscono insieme.
Questo semplifica sia la scrittura del codice sia la gestione degli errori: se un task fallisce, l’intera unità viene annullata in maniera ordinata. È un approccio che favorisce la leggibilità e la robustezza, particolarmente utile per sistemi distribuiti, servizi cloud e microservizi che devono orchestrare più operazioni in parallelo.
- Stable Value API (JEP 502 – Preview)
Gli Stable Values introducono un concetto simile a Optional, ma pensato per contesti multi-thread. Offrono una modalità sicura per condividere valori immutabili e stabili nel tempo, utili per scenari di caching, lazy evaluation o letture consistenti.
In combinazione con Scoped Values e Structured Concurrency, questa API fornisce strumenti moderni per scrivere codice concorrente più leggibile e sicuro, riducendo la complessità tipica della sincronizzazione manuale.
- Sicurezza e crittografia
La sicurezza rimane una priorità della piattaforma. Due novità si distinguono:
- PEM Encodings (JEP 470 – Preview): Java supporta ora in modo nativo la lettura e scrittura di chiavi e certificati in formato PEM, lo standard de facto in OpenSSL e in molte infrastrutture PKI. Questo elimina la necessità di librerie esterne per operazioni comuni nella gestione delle chiavi.
- Key Derivation Function API (JEP 510 – Final): introduce un’API standard per funzioni di derivazione di chiavi (KDF) come PBKDF2 e scrypt, utilizzate per derivare chiavi sicure da password. Questo riduce la dipendenza da implementazioni proprietarie o di terze parti, garantendo interoperabilità e sicurezza by default.
- Vector API (JEP 508 – Tenth Incubator)
Infine, continua l’evoluzione della Vector API, che permette di scrivere operazioni di calcolo parallelo sfruttando le istruzioni SIMD (Single Instruction Multiple Data) delle CPU moderne.
Questa API consente di ottenere performance comparabili al codice nativo in ambiti come machine learning, elaborazione di segnali, crittografia o data analytics, mantenendo la portabilità e la sicurezza tipiche di Java.
Anche se ancora in fase incubator, rappresenta una delle direttrici più promettenti per chi cerca di spingere Java verso scenari ad alte prestazioni.
Le nuove API e le evoluzioni del runtime in Java 25 mirano a:
- semplificare lo sviluppo concorrente, grazie a Scoped Values e Structured Concurrency;
- rafforzare la sicurezza, con strumenti standardizzati per gestione chiavi e KDF;
- aumentare le performance, portando Java sempre più vicino al livello del codice nativo.
Questi miglioramenti confermano la strategia di Java: fornire un linguaggio stabile e familiare, ma al tempo stesso pronto a gestire le esigenze di ambienti cloud-native, microservizi e applicazioni data-intensive.
Ottimizzazioni e Garbage Collector
Oltre alle novità del linguaggio e delle API, Java 25 interviene anche sul cuore della JVM, con ottimizzazioni pensate per ridurre l’overhead, migliorare la gestione della memoria e allineare la piattaforma all’hardware moderno.
- Abbandono del supporto a x86 a 32-bit (JEP 503 – Final)
Java 25 rimuove in modo definitivo il supporto per l’architettura x86 a 32-bit.
Questa scelta ha una motivazione chiara: l’ecosistema server e cloud si è ormai spostato quasi interamente su 64-bit x86_64 e ARM64. Continuare a mantenere la compatibilità con piattaforme ormai residuali rappresentava un costo in termini di manutenzione, testing e complessità del codice.
La rimozione consente di concentrare gli sforzi su architetture moderne, garantendo ottimizzazioni più profonde e un runtime più snello.
- Compact Object Headers (JEP 519 – Final)
Un’altra innovazione importante riguarda la struttura interna degli oggetti Java. Con i Compact Object Headers, la JVM utilizza formati di header più piccoli e compatti per rappresentare informazioni di sincronizzazione e identità degli oggetti.
Il risultato è una riduzione significativa del consumo di memoria per heap di grandi dimensioni, tipici di applicazioni enterprise e microservizi che gestiscono milioni di istanze.
Questo cambiamento è particolarmente vantaggioso in ambienti cloud, dove la memoria rappresenta un costo diretto: minore footprint significa maggiore densità di workload per nodo e una migliore efficienza complessiva.
- Generational Shenandoah GC (JEP 521 – Final)
Lo Shenandoah Garbage Collector, introdotto come low-pause GC, diventa generazionale in Java 25.
Finora Shenandoah gestiva l’heap come un unico spazio; con il modello generazionale, viene introdotta la distinzione tra giovani oggetti (a vita breve) e oggetti longevi, analogamente a quanto già avviene in G1 e ZGC.
I benefici sono notevoli:
- raccolta più rapida degli oggetti temporanei, che costituiscono la maggioranza nelle applicazioni reali;
- minori pause e maggiore throughput, grazie a cicli di GC più brevi;
- migliore efficienza nella gestione della memoria, particolarmente utile per workload con elevata variabilità (es. microservizi e applicazioni data-intensive).
Con questa evoluzione, Shenandoah si posiziona come alternativa solida agli altri GC moderni, offrendo bassa latenza e scalabilità su heap di grandi dimensioni.
Le ottimizzazioni di Java 25 nel runtime vanno lette in chiave di lungo periodo:
- eliminare il supporto a piattaforme obsolete permette di concentrare lo sviluppo sulle architetture di riferimento;
- migliorare la rappresentazione degli oggetti porta a benefici immediati in termini di footprint e costi operativi;
- rendere generazionale Shenandoah significa garantire performance prevedibili e ridotte pause GC in scenari complessi.
Insieme, questi cambiamenti consolidano Java come piattaforma più efficiente, moderna e cloud-ready, in linea con le esigenze di chi sviluppa applicazioni enterprise e distribuite.
Strumenti di diagnostica e osservabilità
Per chi sviluppa e gestisce applicazioni mission-critical o distribuite, la visibilità sul comportamento del sistema è fondamentale. Java 25 arricchisce ulteriormente gli strumenti integrati nella JVM, con nuove funzionalità che migliorano sia la precisione delle analisi sia la riduzione dell’overhead in produzione.
- CPU-time profiling con Java Flight Recorder (JEP 509 – Experimental)
Java Flight Recorder (JFR), lo strumento di profilazione “always-on” della JVM, introduce la possibilità di misurare non solo il tempo di wall-clock (tempo trascorso), ma anche il tempo effettivo di CPU consumato da thread e metodi.
Questa granularità aggiuntiva consente di distinguere in maniera più accurata i colli di bottiglia legati all’elaborazione intensiva da quelli dovuti a attese su I/O o sincronizzazioni.
Per team che gestiscono applicazioni a elevata concorrenza, questo significa poter indirizzare in modo mirato le ottimizzazioni, senza falsi positivi.
- Method-level profiling e Ahead-of-Time profiling (JEP 515 – Final)
Java 25 introduce un profiling a livello di metodo: la JVM può registrare quali metodi vengono eseguiti, con quale frequenza e con quali caratteristiche.
Questi dati possono essere salvati e riutilizzati in seguito, abilitando scenari di ottimizzazione guidata dai profili(profile-guided optimization, PGO).
In parallelo, arriva anche il supporto per l’Ahead-of-Time profiling, che prepara il terreno per futuri compilatori AOT: raccogliere informazioni sull’utilizzo dei metodi consente alla JVM (e in futuro a un compilatore statico) di ottimizzare l’applicazione in fase di build, riducendo startup time e migliorando performance.
- Cooperative sampling (JEP 518 – Final)
Tradizionalmente, il campionamento dei thread avviene a intervalli regolari, con il rischio di introdurre rumore o di campionare in momenti poco rappresentativi. Con cooperative sampling, l’applicazione stessa può suggerire alla JVM i punti in cui è “sicuro” campionare.
Il vantaggio è duplice:
- minore overhead, perché il campionamento non interrompe l’applicazione in momenti critici;
- dati più precisi, grazie a un allineamento migliore con la logica dell’applicazione.
- Method timing e tracing (JEP 520 – Final)
Java 25 introduce la possibilità di registrare tempistiche dettagliate per ogni metodo eseguito da un thread, non solo campioni probabilistici.
Questo rende possibile ricostruire l’intero flusso di chiamate con tempi precisi, utile per:
- identificare hotspot di performance;
- comprendere meglio la concorrenza tra thread;
- correlare ritardi applicativi con sezioni specifiche del codice.
Con queste novità, la JVM diventa ancora più trasparente:
- profiling più accurato a livello di CPU e metodi;
- nuove basi per ottimizzazioni AOT e PGO;
- osservabilità migliorata senza penalizzare le performance in produzione.
Per i team DevOps e SRE, significa poter integrare in pipeline di monitoring e observability strumenti nativi, riducendo la dipendenza da profiler esterni e mantenendo un impatto minimo sull’operatività.
Il messaggio di Java 25 è inequivocabile: la piattaforma si consolida come scelta di riferimento per applicazioni enterprise e cloud-native, rafforzando le sue basi storiche di stabilità e retrocompatibilità, ma introducendo al tempo stesso strumenti moderni per affrontare le sfide attuali.
Maggiore produttività
Le nuove feature del linguaggio riducono la verbosità e aumentano l’espressività. Costrutti come i pattern per i tipi primitivi, i compact source files e i costruttori più flessibili si traducono in meno codice da scrivere e mantenere. Per i team significa maggiore velocità nello sviluppo, meno boilerplate e un ciclo di revisione più snello.
Concorrenza e workload moderni
Le Scoped Values, la Structured Concurrency e la Stable Value API rispondono direttamente alle esigenze del multithreading contemporaneo, dove i workload distribuiti e le Virtual Threads richiedono modelli di programmazione meno complessi e più sicuri. Questo rende il linguaggio più adatto a microservizi, sistemi reattivi e piattaforme cloud-native che devono scalare in modo dinamico.
Osservabilità integrata
Le nuove capacità di profiling, tracing e sampling rendono la JVM più trasparente senza bisogno di strumenti esterni pesanti. Per i team DevOps e SRE questo significa poter integrare i dati di runtime direttamente nelle pipeline di observability e monitoring, riducendo tempi di diagnostica e migliorando la capacità di rispondere agli incidenti.
Performance e footprint ottimizzati
Con i Compact Object Headers e il Generational Shenandoah GC, Java 25 riduce il consumo di memoria e rende la gestione degli heap più efficiente. Ciò si traduce in costi operativi più bassi in cloud (meno risorse per workload equivalenti) e in una migliore prevedibilità delle performance in scenari mission-critical.
Aggiornare conviene
Per chi è ancora su Java 21, l’ultimo LTS, il salto a Java 25 rappresenta un upgrade incrementale ma concreto:
- non introduce strappi architetturali,
- consolida le innovazioni già introdotte con Java 17 e 21,
- aggiunge un set di strumenti maturi che agevolano la scrittura, la manutenzione e il monitoraggio del software.
In prospettiva, rimanere indietro significherebbe rinunciare a un linguaggio più snello, a strumenti di osservabilità avanzati e a miglioramenti che incidono direttamente su time-to-market, qualità del codice e costi infrastrutturali.
Con Java 25 la piattaforma conferma la sua capacità di innovare senza sacrificare la stabilità, un equilibrio che ha sempre distinto l’ecosistema Java rispetto ad altri linguaggi. Questo nuovo LTS non è un cambiamento radicale, ma una tappa di consolidamento che rende il linguaggio più espressivo, le API più vicine alle esigenze moderne e il runtime più efficiente.
Per gli sviluppatori significa ridurre complessità e boilerplate, adottare strumenti più potenti per la concorrenza e avere osservabilità nativa direttamente nella JVM. Per le aziende, invece, significa poter contare su una piattaforma che garantisce continuità, sicurezza e costi operativi ottimizzati, elementi cruciali in un’era cloud-first.
In prospettiva, Java 25 getta le basi per le sfide che attendono la comunità:
- l’ahead-of-time compilation, già preparata con le nuove opzioni di profiling e sperimentazioni AOT;
- una concurrency avanzata, che mette al centro modelli più semplici e sicuri per workload distribuiti;
- una gestione più efficiente delle risorse, fondamentale in ambienti multi-tenant e microservizi.
Fonti
- OpenJDK. (2025). JDK 25 Release Notes. https://openjdk.org/projects/jdk/25/
- Oracle. (2025). JEP Index. https://openjdk.org/jeps/0
- Goetz, B., Rose, J., & Reinhold, M. (2024). Java Language Futures: Pattern Matching and Concurrency. InfoQ.
Autore: Martina Pegoraro





