Java 25 : quelles nouveautés pour le successeur de Java 21 ?
Java 25 est la toute nouvelle version Long-Time Support (LTS) de Java. Elle est sortie le 16 septembre 2025. Elle succède à Java 21, sortie deux ans plus tôt, version qui avait intégré de nombreuses améliorations en particulier sur la simplification du langage (Pattern Matching for Switch, Record Patterns) et sur la gestion de la concurrence avec les Virtual Threads.
Qu’en est-il de Java 25 ? Quelles sont les nouveautés et améliorations apportées par cette version ?
Découvrons-le à travers ce tour d’horizon des évolutions introduites depuis Java 21.
Java, un langage qui accélère sa transformation
Java 25 apporte son lot de nouveautés et d’améliorations, continuant sur la lancée des versions précédentes. Depuis Java 21, plusieurs versions intermédiaires (Java 22, 23 et 24) ont introduit des fonctionnalités intéressantes, notamment dans le domaine de la simplification du langage et dans l’optimisation des performances en particulier dans les temps de démarrage des applications Java, ou encore dans l’évolution de ses APIs, mais aussi en termes de sécurité en préparant l’arrivée future de l’informatique quantique capable de casser les algorithmes de cryptographie actuels.
Au total, ce sont plus de 20 JEPs (Java Enhancement Proposals) qui ont été intégrées et finalisées depuis Java 21.
Ces évolutions confirment que Java continue de renforcer sa position en tant que langage de programmation moderne et performant, tout en restant fidèle à ses principes fondamentaux de simplicité, de portabilité et de robustesse.
Les évolutions du langage Java
Java 25 introduit des évolutions notables dans le langage, visant à améliorer la lisibilité et la maintenabilité du code, tout en simplifiant sa syntaxe. Voici les nouveautés apportées sur ce point depuis Java 21 :
JEP 456 : Unamed Variables & Pattern
Que ce soit pour des raisons de style de code ou parce que le langage Java le requière, les développeurs sont amenés à déclarer des variables dans certains contextes, mais sans les utiliser.
Par exemple, le bloc catch est écrit sous cette forme, où le paramètre d’exception ex n’est pas utilisé :
String s = ...;
try {
int i = Integer.parseInt(s);
... i ...
}
catch (NumberFormatException ex) {
System.out.println("Bad number: " + s); // ex est non utilisée
}
Dans Java 25, les variables inutilisées peuvent être déclarées avec le nom de variable « _ » (underscore). Par exemple, le bloc catch précédent peut être réécrit ainsi :
String s = ...;
try {
int i = Integer.parseInt(s);
... i ...
}
catch (NumberFormatException _) { // Unnamed variable
System.out.println("Bad number: " + s);
}Cette syntaxe est valable également au sein des paramètres de méthode, dans les expressions lambda, dans le pattern matching, etc.
JEP 467: Markdown Documentation Comments
Jusqu’à présent, les commentaires de documentation en Java étaient principalement rédigés en HTML, ce qui pouvait rendre la lecture et l’écriture de la documentation plus complexe. Avec l’introduction de JEP 467, Java 25 permet désormais d’utiliser le format Markdown pour les commentaires de documentation. Cela simplifie grandement la création de documentation, rendant le processus plus intuitif et accessible pour les développeurs. Le support de Markdown permet également une meilleure intégration avec divers outils de documentation et plateformes de développement.
JEP 511 : Module Import Declarations
Java 25 introduit la possibilité d’importer les packages requis dans le code source Java avec une seule déclaration import module dans le fichier source Java. Cela simplifie la gestion des dépendances et améliore la lisibilité du code en réduisant le nombre de lignes nécessaires pour importer plusieurs packages d’un même module.
Exemple avant Java 25 :
import java.util.Map; // or import java.util.*;
import java.util.function.Function; // or import java.util.function.*;
import java.util.stream.Collectors; // or import java.util.stream.*;
import java.util.stream.Stream; // (can be removed)
...
String[] fruits = new String[] { "apple", "berry", "citrus" };
Map<String, String> m =
Stream.of(fruits)
.collect(Collectors.toMap(s -> s.toUpperCase().substring(0,1),
Function.identity()));Exemple avec Java 25 :
import module java.base; // Import all exported packages from java.base
...
String[] fruits = new String[] { "apple", "berry", "citrus" };
Map<String, String> m =
Stream.of(fruits)
.collect(Collectors.toMap(s -> s.toUpperCase().substring(0,1),
Function.identity()));
JEP 512: Compact Source Files and Instance Main Methods
Comparé à d’autres langages, Java est assez verbeux. Pour simplifier sa syntaxe, il est désormais possible de coder en Java de manière compacte. Cette évolution est particulièrement utile pour les développeurs découvrant le langage Java. Cela leur permet de se familiariser plus facilement avec la syntaxe de Java sans avoir à aborder des notions plus complexes comme les classes, packages, modules ou les attributs de visibilité, qui peuvent être déroutants à ce stade de leur apprentissage. Elle est particulièrement adaptée lorsqu’on souhaite écrire des programmes Java dans un style plus concis, similaire à celui des scripts.
Elle permet de :
- Adopter une forme compacte des fichiers sans déclarer une classe superflue
- Remplacer la méthode public static void main(String[] args) par une méthode d’instance main() plus simple et compréhensible.
- Inclure une nouvelle classe dans le package java.lang pour fournir des méthodes I/O simplifiées et plus compréhensibles (que le fameux System.out.println) pour les débutants.
- L’import automatique d’APIs standards du package java.lang lorsque le code est écrit dans un format compact (voir point 1).
Exemple avant Java 25 :
class HelloWorld {
void main() {
System.out.println("Hello, World!");
}
}Exemple avec Java 25 :
main() {
IO.println("Hello, World! in compact style");
}
JEP 513 : Flexible Constructor Bodies
Dans les précédentes versions LTS, il n’était pas possible d’écrire des instructions avant l’appel au constructeur parent de la classe (méthode super()). Dans certains cas, cela pouvait entraîner des appels inutiles, notamment lorsque des validations de paramètres étaient nécessaires avant l’initialisation de l’objet. Le langage permet désormais de pouvoir écrire des instructions avant l’appel à super(), ce qui offre plus de flexibilité dans la gestion de l’initialisation des objets.
Exemple de code avec la mise en œuvre de cette évolution :
public class PositiveBigInteger extends BigInteger {
private final long max;
public PositiveBigInteger(long value, long max) {
// Code avant l'appel à super()
if (value <= 0)
throw new IllegalArgumentException("non-positive value");
this.max = max;
// Appel à super() en dernier : Evite les appels inutiles au constructeur parent si une exception est levée en amont (pas possible avant)
super(value);
}
}
Les amélioration des performances avec Java 25
Java 25 marque un avancement majeur sur l’amélioration des performances, notamment en intégrant des évolutions portées par le projet Leyden.
Le projet Leyden a pour objectif de réduire le temps de démarrage et la consommation mémoire des applications Java, afin d’améliorer leurs performances, en particulier dans les environnements cloud-native et serverless. Jusqu’à présent, la principale solution pour obtenir un démarrage quasi instantané reposait sur les applications natives compilées avec GraalVM Native Image, capables de démarrer en quelques millisecondes. Toutefois, cette approche présente plusieurs limites : temps et coût de compilation élevés, support partiel de la réflexion et de certaines bibliothèques, ainsi qu’un throughput parfois inférieur à celui de la JVM classique.
Avec Java 25, l’OpenJDK entend combiner les atouts de la JVM (compatibilité, optimisations dynamiques, écosystème mature) avec un démarrage significativement accéléré, grâce à l’introduction d’un mécanisme de caching Ahead-Of-Time permettant de précompiler certaines parties du code.
Cache Ahead-Of-Time (AOT) (JEPs 483, 514 et 515)
Java 25 améliore considérablement les performances des applications Java grâce à la création d’un cache Ahead-Of-Time (AOT).
Le cache AOT (Ahead-Of-Time) introduit par les JEP 483 et 514 permet d’améliorer significativement le temps de démarrage des applications Java. Ce cache est construit lors d’un run d’entrainement de l’application Java, qui enregistre les classes et méthodes utilisées, puis génère un cache AOT optimisé pour ces classes et méthodes. Lors du démarrage de l’application, ce cache est chargé en mémoire, ce qui permet de réduire le temps de compilation Just-In-Time (JIT) et d’améliorer ainsi le temps de démarrage global de l’application.
La JEP 515 permet également d’intégrer au cache AOT des informations de profilage collectées par le JIT. Le cache AOT est ainsi plus efficace, car il est optimisé en fonction de l’utilisation réelle de l’application.
Les gains de performance sont particulièrement notables pour les applications avec un grand nombre de classes et de méthodes, où le temps de démarrage peut être réduit de manière significative. Selon les applications, un démarrage jusqu’à 50% plus rapide peut être observé.
Commande pour construire le cache AOT, il faut ajouter l’option -XX:AOTCacheOutput:
$ java -XX:AOTCacheOutput=app.aot -cp app.jar com.example.App ...Pour lancer l’application avec le cache AOT précédemment construit, il faut ajouter l’option -XX:AOTCache:
$ java -XX:AOTCache=app.aot -cp app.jar com.example.App ...
JEP 519: Compact Object Headers
Des améliorations sur la gestion des entêtes des objets ont été apportées pour réduire leur taille. En optimisant la structure des en-têtes d’objets, Java 25 permet de diminuer la consommation mémoire des applications, ce qui est particulièrement bénéfique pour les applications avec un grand nombre d’objets en mémoire. Cette optimisation contribue également à améliorer les performances globales des applications Java, notamment en réduisant la pression sur les sollicitations du Garbage Collector (GC).
Afin de valider la stabilité de cette évolution, de nombreux tests ont été réalisés par Oracle et Amazon sur des centaines de services en production. Les résultats montrent une réduction de la consommation mémoire allant jusqu’à plus de 20% dans certains cas, avec des réductions dans les temps de traitements allant jusqu’à 10% et des passages du GC moins jusqu’à 15% moins fréquents.
Cette option est par défaut désactivée. Pour l’activer, il faut ajouter l’option -XX:+CompactObjectHeaders à la JVM.
Evolution des Garbage Collectors (GC)
Le langage Java dispose de nombreux Garbage Collectors (GC) pour répondre aux différents besoins des applications Java. Dans Java 25, quelques améliorations ont été réalisés sur les Garbage Collectors G1, ZGC et Shenandoah.
Shenandoah est un GC à faible latence qui vise à minimiser les pauses de l’application en effectuant la plupart de son travail de collecte en parallèle de l’exécution de l’application. Shenandoah n’est pas le GC par défaut dans Java. Il est plutôt préconisé pour des applications avec une heap énorme, telles les applications BigData. Via la JEP 521, le mode générationnel lui a été ajouté. Le mode par défaut "non-générationnel" est toujours disponible. Pour activer le mode générationnel de Shenandoah, il suffit d’ajouter l’option -XX:ShenandoahGCMode=generational à la JVM.
Le mode générationnel a été également ajouté au Garbage Collector ZGC à travers la JEP 474, dépréciant par la même occasion le mode non-générationnel. Le mode générationnel étant plus performant dans la plupart des cas que le mode non-générationnel, les futurs développements se concentreront sur ce mode-ci.
Enfin, le Garbage Collector par défaut de Java 25, le G1, a également bénéficié d’améliorations via la JEP 423. Ces améliorations visent à réduire les pauses du G1 lors d’opérations faisant appels à des fonctions JNI (Java Native Interface).
Java 25 : les évolutions de ses APIs
Les bibliothèques standards du langage Java continuent à évoluer avec Java 25, avec comme objectifs de fournir toujours plus de fonctionnalités aux développeurs.
JEP 502 : Scoped Values
Les Scoped Values sont des conteneurs qui permettent de partager efficacement des données immuables entre une méthode et ses appelées dans le même thread, ainsi qu’avec les threads enfants, sans recourir aux paramètres de méthodes. Contrairement aux variables, une ScopedValue est définie une seule fois et reste disponible en lecture pendant une période d’exécution délimitée.
Les Scoped Values sont particulièrement pertinentes dans le contexte des Virtual Threads en offrant des coûts d’espace mémoire et de performance réduits par rapport aux ThreadLocals traditionnels. Les Virtuals Threads sont légers et éphémères. Nous pouvons en posséder plusieurs millions sur une application. L’utilisation de ThreadLocals peut entraîner une consommation mémoire excessive et des fuites de mémoire si les ThreadLocals ne sont pas correctement nettoyés lors de leur utilisation combinée avec les Virtual Threads. Les Scoped Values sont conçues pour être utilisées avec les Virtual Threads, mais elles fonctionnent également avec les threads traditionnels.
L’exemple suivant montre une API qui définit l’utilisateur connecté en tant que scoped value :
public class ScopedValuesExample {
// Logger
private static final Logger log = Logger.getLogger(ScopedValuesExample.class.getName());
// Déclaration d'une ScopedValue
private static final ScopedValue<String> USERNAME = ScopedValue.newInstance();
public static void main(String[] args) {
// Définir le scope avec une valeur
ScopedValue.where(USERNAME, "Alice").run(() -> {
log.info("Dans le scope principal");
methodA(); // Peut accéder à USERNAME sans paramètre
}); // USERNAME n'est plus accessible ici
// Tentative d'accès en dehors du scope (lève une exception)
try {
String user = USERNAME.get(); // Exception !
} catch (NoSuchElementException e) {
log.info("USERNAME n'est pas accessible en dehors du scope");
}
}
private static void methodA() {
// Accès direct à la valeur depuis n'importe quelle méthode dans le scope
String user = USERNAME.get();
log.info("Method A - Utilisateur: " + user);
methodB(); // Appel d'une méthode plus profonde
}
private static void methodB() {
// La valeur reste accessible même dans les appels imbriqués
String user = USERNAME.get();
log.info("Method B - Utilisateur: " + user);
}
}
JEP 485: Stream Gatherers
Les Stream Gatherers représentent une évolution de l’API Stream. Les Gatherers permettent de créer des opérations intermédiaires personnalisées pour les Streams. À noter qu’il était déjà possible de créer des opérations terminales personnalisées au travers de l’interface Collector.
Voici un exemple reproduisant l’opération intermediaure Gatherers.limit().
Gatherer<String, ?, String> limit() {
class Counter {
int counter;
Counter(int counter) { this.counter = counter; }
}
return Gatherer.ofSequential(
() -> new Counter(0),
(counter, element, downstream) -> {
if (counter.counter++ == 3) {
return false;
}
return downstream.push(element);
}
);
}Néanmoins, il est moins efficace de créer des opérations intermédiaires personnalisées qui reproduisent des fonctionnalités déjà disponible (comme l’exemple du limit() ci-dessus). En effet, ces opérations ne bénéficient pas de toutes les optimisations du compiler JIT.
JEP 491 : Synchronize Virtual Threads without Pinning
Les Virtual Threads représentent l’évolution majeure introduite avec Java 21. Leur intégration dans l’écosystème Java a été significativement optimisée. Cette fonctionnalité vise deux objectifs principaux :
- Faciliter l’adaptation des bibliothèques Java existantes aux threads virtuels, sans nécessiter de modifications pour éviter l’usage de méthodes ou d’instructions synchronized.
- Améliorer les outils de diagnostic afin d’identifier plus efficacement les cas où les threads virtuels restent liés aux platform threads (phénomène de pinning), empêchant leur libération. Les Virtual Threads sont l’évolution phare de Java 21. Leur intégration à l’écosystème Java a été améliorée.
JEP 484 : Class-File API
Avec cette évolution, il est à présent possible de générer des classes Java dynamiquement au moment de l’exécution. Cela ouvre la voie à des cas d’utilisation avancés tels que la génération de code à la volée, la création de proxies dynamiques, et d’autres scénarios où la flexibilité et la dynamique sont essentielles.
Voici un exemple simple de génération d’une classe Java avec la Class-File API :
ClassBuilder classBuilder = ...;
classBuilder.withMethod(
"fooBar",
MethodTypeDesc.of(CD_void, CD_boolean, CD_int),
flags,
methodBuilder -> methodBuilder.withCode(
codeBuilder -> {
Label label1 = codeBuilder.newLabel();
Label label2 = codeBuilder.newLabel();
codeBuilder.iload(1)
.ifeq(label1)
.aload(0)
.iload(2)
.invokevirtual(ClassDesc.of("Foo"), "foo", MethodTypeDesc.of(CD_void, CD_int))
.goto_(label2)
.labelBinding(label1)
.aload(0)
.iload(2)
.invokevirtual(ClassDesc.of("Foo"), "bar", MethodTypeDesc.of(CD_void, CD_int))
.labelBinding(label2);
.return_();
}
)
);Le code généré est équivalent au code Java ci-dessous :
void fooBar(boolean z, int x) {
if (z)
foo(x);
else
bar(x);
}
JEP 454 : Foreign Function & Memory API
La création de l’API FFM (Foreign Function & Memory) ouvre désormais l’accès au code et aux données gérées en dehors de la JVM. Cette API permet d’invoquer de manière sécurisée du code natif (C, C++, etc.) et d’accéder à des blocs de mémoire en dehors du tas de la JVM.
Le code suivant montre un exemple simple d’utilisation de l’API FFM pour appeler la fonction C strlen qui calcule la longueur d’une chaîne de caractères :
public class FFMTest {
public static void main(String[] args) throws Throwable {
// 1. Get a lookup object for commonly used libraries
SymbolLookup stdlib = Linker.nativeLinker().defaultLookup();
// 2. Get a handle to the "strlen" function in the C standard library
MethodHandle strlen =
Linker.nativeLinker()
.downcallHandle(
stdlib.find("strlen").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS));
// 3. Get a confined memory area (one that we can close explicitly)
try (Arena offHeap = Arena.ofConfined()) {
// 4. Convert the Java String to a C string and store it in off-heap memory
MemorySegment str = offHeap.allocateFrom("Happy Coding!");
// 5. Invoke the foreign function
long len = (long) strlen.invoke(str);
System.out.println("len = " + len);
}
// 6. Off-heap memory is deallocated at end of try-with-resources
}
}
JEP 472 : Prepare to Restrict the Use of JNI
Java 25 offre la possibilité d’appeler du code natif via l’interface Java Native Interface (JNI) ou l’API Foreign Function & Memory (FFM). Le chargement de code natif étant restreint dans l’API FFM, un avertissement est émis par défaut au moment de l’exécution.
Afin d’obtenir un fonctionnement cohérent entre JNI et FFM, l’utilisation de JNI provoque elle aussi l’émission d’un avertissement lors de l’exécution de code natif.
Messages remontés lors de l’utilisation de JNI ou FFM API :
WARNING: A restricted method in java.lang.foreign.Linker has been called
WARNING: java.lang.foreign.Linker::downcallHandle has been called by com.example.Main in an unnamed module
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabledPour désactiver les messages d’avertissement pour l’ensemble du code java, nous pouvons utiliser l’option --enable-native-access=ALL-UNNAMED :
java --enable-native-access=ALL-UNNAMED ...Dépréciation des méthodes du package sun.misc.Unsafe
Les JEPs 471 et 498 ont pour objectif de préparer l’écosystème à la suppression des méthodes d’accès mémoire via l’API sun.misc.Unsafe (apparue en 2002 et qui sera supprimée complètement à partir de Java 26). Les méthodes de ces APIs sont considérées comme dangereuses car elles permettent d’accéder directement à la mémoire, ce qui peut entraîner des problèmes de sécurité et de stabilité de l’application. Il est préconisé de remplacer les appels à cette API par la toute nouvelle API Foreign Function & Memory (FFM) introduite dans Java 25 (voir ci-dessus via la JEP 454)
Un avertissement est émis lorsqu’une application utilise directement ou indirectement ces méthodes.
JEP 458 : Launch Multi-File Source Code Programs
Depuis Java 11, il est possible de lancer un programme depuis un fichier source .java sans étape de compilation préalable. Le launcher Java compile dès lors le programme en mémoire automatiquement avant son exécution.
La JEP 458 ouvre la voie à une exécution simplifiée des programmes Java, en permettant le lancement d’un fichier source utilisant une classe définie dans un autre fichier source, ce dernier étant compilé automatiquement en mémoire. Les fichiers sources sont recherchés dans la hiérarchie de répertoire habituelle en Java qui reflète la structure des packages.
Seuls les fichiers source utilisés par le programme principal seront compilés en mémoire.
JEP 486 : Permanently Disable the Security Manager
Le gestionnaire de sécurité n’est que très rarement utilisé pour sécuriser le code côté serveur et sa maintenance est coûteuse. Cette fonctionnalité a déjà été dépréciée dans Java 17.
Du fait de sa faible adoption et de l’abandon de son support dans la plupart des frameworks et outils, le Security Manger a donc été définitivement désactivé et n’est plus disponible dans Java 25.
JEP 503: Remove the 32-bit x86 Port
Le support de l’architecture 32-bit x86 est supprimé dans Java 25.
Le coût de maintenance de cette architecture est devenu trop élevé par rapport à son utilisation réelle. En effet, la majorité des systèmes modernes utilisent des architectures 64-bit, et le support des architectures 32-bit est devenu de moins en moins pertinent.
Java se prépare à l’ère post-quantique
Anticipant les futurs développements de l’informatique quantique qui pourront rendre vulnérables les algorithmes de cryptographies actuels, il est primordial pour java de construire dès aujourd’hui les fondations nécessaires pour intégrer des mécanismes de chiffrement hybrides et résistants aux attaques quantiques dans les années à venir.
Avec la JEP 510, Java est capable de supporter l’algorithme HKDF (HMAC-based Key Derivation Function) défini dans la RFC 5869. Cet algorithme est utilisé pour dériver des clés secrètes à partir d’une clé initiale et d’un sel (salt) optionnel, en utilisant une fonction de hachage cryptographique sous-jacente.
Exemple de création d’une clé secrète dérivée avec HKDF-SHA256 :
// Create a KDF object for the specified algorithm
KDF hkdf = KDF.getInstance("HKDF-SHA256");
// Create an ExtractExpand parameter specification
AlgorithmParameterSpec params =
HKDFParameterSpec.ofExtract()
.addIKM(initialKeyMaterial)
.addSalt(salt).thenExpand(info, 32);
// Derive a 32-byte AES key
SecretKey key = hkdf.deriveKey("AES", params);
// Additional deriveKey calls can be made with the same KDF objectA l’avenir, de nouvelles évolutions devraient voir le jour, Java souhaitant ajouter d’autres algorithmes KDF dans les futures versions du JDK tels que Argon2.
De plus, les JEPs 496 et 497 introduisent des mécanismes de chiffrement et de signature numérique résistants aux attaques quantiques, basés sur des algorithmes de cryptographie post-quantique tels que le ML-KEM (Module-Lattice-Based Key-Encapsulation Mechanism) et le ML-DSA (Module-Lattice-Based Digital Signature Algorithm).
Java 25, le profiling au cœur de la JVM
Java Flight Recorder (JFR) s’impose comme l’outil de référence pour le profiling des applications Java.
A travers la JEP 518, son fonctionnement a été repensé pour diminuer son impact sur les performances des applications tout en offrant une analyse plus fine et plus précise des performances.
A travers la JEP 520, des nouvelles capacités ont été intégrées pour collecter des informations de tracing et de timing des méthodes. Il est ainsi possible de recueillir des données fiables et précises sur le nombre d’invocations d’une méthode, de diagnostiquer plus efficacement des problèmes de performance, et d’optimiser le code en conséquence.
Que nous réserve les futures versions du langage Java ?
Java 25 embarque également des évolutions en incubation, en preview ou au stade d’expérimentation. Ces évolutions ne sont pas encore dans un état stable et/ou requièrent des retours de la communauté avant d’être intégrées de manière définitive dans le JDK. Elles offrent un aperçu des orientations futures du langage et de la plateforme Java.
Voici les évolutions présentes mais non finalisées dans Java 25 :
- JEP 507: Primitive Types in Patterns, instanceof, and switch (3ème Preview) : cette évolution a pour objectif de disposer d’une syntaxe uniforme pour tous les types de patterns (record, switch, instanceof) en offrant la possibilité d’utiliser les types primitifs (non possible actuellement).
- JEP 502: Stable Values (Preview) : cette évolution permettra de différer l’initialisation des attributs immuables d’une classe afin d’améliorer les performances en évitant des calculs inutiles lors de l’initialisation de l’objet (ex: déclaration d’un logger généralement en static final qui ne sera potentiellement jamais utilisé), tout en garantissant que la valeur reste immuable après sa première affectation.
- JEP 505: Structured Concurrency (5ème Preview) : la concurrence structurée représente une approche moderne, rendue possible par les Virtual Threads, pour diviser les tâches en sous-tâches et les exécuter en parallèle dans différents threads tout en facilitant la gestion de leur cycle de vie et notamment la gestion des erreurs.
- JEP 470: PEM Encodings of Cryptographic Objects (Preview) : cette évolution permettra de lire et d’écrire des objets cryptographiques (clés, certificats, etc.) au format PEM (Privacy-Enhanced Mail), un format de fichier couramment utilisé pour stocker et échanger des données cryptographiques, mais qui n’était pas pris en charge nativement par Java jusqu’à présent.
- JEP 489 : Vector API (10ème Incubation) : dixième incubation pour l’API Vector, qui a pour objectif de fournir des opérations vectorielles performantes pour le traitement de données en parallèle, et ainsi gagner de manière significative en performance pour les applications de calcul intensif.
Conclusion
Java 25 est une version LTS qui apporte de nombreuses améliorations et nouveautés dans divers domaines : performance, sécurité, amélioration du code et des APIs, profiling, etc.
A travers cette version, l’OpenJDK continue de faire évoluer le cœur du langage Java et accélère l’intégration des travaux du projet Leyden pour améliorer la performance des applications Java, en particulier sur le temps de démarrage et la consommation mémoire, deux points critiques pour les applications cloud natives.
Java 25 continue également d’améliorer l’expérience des développeurs avec des nouveautés pour simplifier le code et rendre le langage Java plus accessible aux débutants, et aux développeurs venant d’autres langages.
Le profiling des applications Java est également renforcé avec plusieurs évolutions de Java Flight Recorder (JFR) pour offrir une analyse plus fine et plus précise des performances des applications tout en diminuant l’impact sur les performances des applications.
Enfin, Java 25 prépare l’avenir en introduisant des évolutions pour anticiper les futurs développements de l’informatique quantique avec la création d’une API KDF (Key Derivation Function).
Pour en savoir plus :
https://openjdk.org/projects/jdk/25/
https://openjdk.org/projects/jdk/24