Java 25 est sorti en septembre 2025 en tant que nouvelle version Long Term Support (LTS), deux ans après Java 21. Durant cet intervalle, les versions intermédiaires Java 22, 23 et 24 ont introduit plus d’une vingtaine de nouvelles fonctionnalités et améliorations Celles-ci concernent notamment la simplification du langage, l’optimisation des performances (temps de démarrage des applications réduit), l’évolution des API standard ainsi que le renforcement de la sécurité en prévision de l’ère post-quantique.
Dans cet article, nous allons passer en revue, version par version (de Java 22 à Java 25), les nouveautés marquantes apportées depuis Java 21.
Import de modules (Module Import Declarations - Java 25) – Introduction de la syntaxe import module, permettant d’importer des modules entiers directement dans des fichiers Java classiques.
// Before
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Map<String, String> m =
Stream.of(fruits)
.collect(Collectors.toMap(s -> s.substring(0,1).toUpperCase(),
Function.identity()));
// With Java 25
import module java.base;
Map<String, String> m =
Stream.of(fruits)
.collect(Collectors.toMap(s -> s.substring(0,1).toUpperCase(),
Function.identity()));
Fichiers sources compacts (Compact Source Files And Instance Main Methods - Java 25) – Il est désormais possible d’écrire des programmes Java de manière plus concise. Java 25 permet de définir directement une méthode main() d’instance dans un fichier source, sans déclarer de classe englobante ni de méthode public static void main classique. Ce nouveau mode s’accompagne d’une classe utilitaire java.lang.IO fournissant des méthodes d’E/S simplifiées (par exemple IO.println au lieu de System.out.println).
// Before
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
// With Java 25
main() {
IO.println("Hello World!");
}
Constructeurs flexibles (Flexible Constructor Bodies - Java 25) – Les constructeurs Java peuvent désormais contenir des instructions avant l’appel au constructeur parent (super()). Autrement dit, on peut effectuer des validations ou initialisations préalables avant d’appeler le constructeur de la classe parente. Cela apporte plus de flexibilité et évite des appels inutiles à super() en cas d’erreur de validation.
Performances et démarrage accéléré (Java 25) – Java 24 et Java 25 marquent une avancée importante en matière de performances, en intégrant des évolutions issues du projet Leyden. Celui-ci vise à réduire le temps de démarrage et la consommation mémoire des applications Java, en particulier pour les environnements cloud-native et serverless.
Jusqu’à présent, les démarrages quasi instantanés reposaient principalement sur les applications natives via GraalVM Native Image, au prix de contraintes notables (temps de compilation élevés, limitations de la réflexion). Avec Java 25, l’OpenJDK cherche à combiner les atouts de la JVM classique avec un démarrage fortement accéléré, grâce à un mécanisme de pré-compilation Ahead-Of-Time avec mise en cache, permettant de réutiliser une partie du travail dès le lancement.
Scoped Values (Java 25) – Finalisée dans Java 25, l’API Scoped Values fournit une alternative sûre aux variables thread-local pour partager des données immuables sur un ensemble de méthodes exécutées dans le même thread (y compris ses threads enfants virtuels). Une Scoped Value se définit pour une portée d’exécution donnée via ScopedValue.where(...) et est accessible en lecture dans tout le code appelé dans ce scope, sans nécessiter de passer la valeur en paramètre. Elle disparaît automatiquement en dehors du scope. Cette approche, particulièrement utile avec les threads virtuels, évite les fuites mémoire et la surcharge associées aux ThreadLocal.
Fin du support 32-bit (Java 25) – Java 25 abandonne la prise en charge des systèmes 32 bits x86 (JEP 503).
Threads virtuels améliorés (Java 24) – Amélioration de l’évolutivité des applications Java qui utilisent des threads virtuels avec des blocs ou méthodes synchronized, pour que ces threads ne restent bloqués inutilement sur un thread plateforme.
Stream Gatherers (Java 24) – Évolution de l’API Stream permettant de définir de nouvelles opérations intermédiaires personnalisées sur les streams via la nouvelle méthode Stream::gather(Gatherer). Par exemple, on peut définir un gatherer équivalent à une nouvelle opération limit spécifique ou pour grouper par exemple des éléments par paires.
// Without Gather
List<String> names = List.of("Alex", "John", "James", "Michael");
List<String> pairs = IntStream.range(0, names.size() - 1)
.mapToObj(i -> names.get(i) + " - " + names.get(i + 1))
.toList();
System.out.println(pairs); // [Alex - John, John - James, James - Michael]
// With Gatherer
Gatherer<String, ?, String> pairing = Gatherer.ofSequential(
// Initial state: an object holding the previous element.
() -> new Object() { String prev; },
// For each element:
// - if prev exists, push "prev - element"
// - set prev = element
(state, element, downstream) -> {
if (state.prev != null) {
downstream.push(state.prev + " - " + element);
}
state.prev = element;
// Return true to continue gathering.
// If the accumulator returns false, gathering stops immediately: the gatherer
// will stop receiving elements and will not produce more outputs.
return true;
}
);
// Apply the gatherer to the stream of names to produce a list of paired strings ("previous - current").
List<String> pairs = names.stream().gather(pairing).toList();
System.out.println(pairs); // [Alex - John, John - James, James - Michael]
Class-File API (Java 24) – Ajout d'une API permettant la manipulation de fichiers de classe Java. Grâce à cette API, il est possible de produire des classes en bytecode à la volée au runtime.
Sécurité et cryptographie (Java 24) – Deux JEPs (496 et 497) ont introduit la prise en charge d’algorithmes de cryptographie résistants aux ordinateurs quantiques : un mécanisme d’encapsulation de clés (KEM) et un schéma de signature numérique basés sur des problèmes mathématiques de type lattice. Ces algorithmes, destinés à anticiper la vulnérabilité future des méthodes cryptographiques actuelles, sont disponibles en tant qu’extensions de l’API de sécurité. Par ailleurs, Java 24 a définitivement désactivé le Security Manager (obsolète depuis Java 17).
JavaDoc en Markdown (Markdown Documentation Comments - Java 23) – La rédaction de la JavaDoc peut être réalisée en utilisant la syntaxe Markdown au lieu du HTML brut.
/// # Validation utilities
/// Provides helper methods to validate:
/// - emails
/// - phone numbers
/// - usernames
public final class ValidationUtils {
}
Préparation aux changements (Java 23) – Certaines fonctionnalités héritées ont été déclarées dépréciées afin d’annoncer leur retrait futur. Notamment, les méthodes non sécurisées du package sun.misc.Unsafe (accès mémoire bas niveau) ont été marquées pour suppression prochaine.
Variables anonymes _ (Unnamed Variables & Patterns - Java 22) – Marque explicitement les variables ou paramètres inutilisés.
try {
int valeur = Integer.parseInt(input);
// ... utilisation de valeur ...
} catch (NumberFormatException _) {
System.out.println("Valeur incorrecte : " + input);
}
Foreign Function & Memory (FFM) (Java 22) – L’API FFM est devenue stable et permet d’appeler du code natif (écrites en C, C++…) ainsi que de manipuler de la mémoire hors du tas Java sans utiliser JNI. Elle simplifie l’interaction avec les bibliothèques natives tout en garantissant la sécurité des accès mémoire.
Exécution de fichiers source multiples (Launch Multi-File Source-Code Programs - Java 22) – Depuis Java 11, on pouvait lancer un programme Java directement à partir d’un fichier source unique (java MonFichier.java). Désormais, on peut inclure plusieurs fichiers sources dépendants lors de l’exécution. Par exemple, java Main.java Util.java compilera en mémoire Util.java si la classe Main en dépend, et exécutera Main directement.
En résumé, Java 25 apporte une multitude d’évolutions qui modernisent encore la plateforme Java. Entre simplifications syntaxiques, outillage enrichi, performances accrues et anticipation des besoins futurs (quantique, cloud natif), cette version LTS offre un écosystème Java à la fois plus productif pour les développeurs et plus efficace en exécution. Migrer vers Java 25 permet de bénéficier de ces avantages tout en pérennisant vos applications pour les années à venir.
Aujourd’hui, seules les versions encore officiellement supportées doivent être privilégiées en production. Elles bénéficient de correctifs de sécurité, de mises à jour régulières et d’un écosystème actif, garantissant stabilité, performances et pérennité des applications. Choisir une technologie supportée, c’est réduire les risques techniques et faciliter l’évolution future des systèmes. Vous trouverez ici la roadmap des versions encore supportées : OpenJDK on RHEL / Temurin.
L'écriture de cet article s'appuie sur les articles suivants :
À noter que cet article, pour des besoins de test, a été en partie rédigé par une IA et presque entièrement reformulé, complété et vérifié par un humain.