Java 27, publié le 15 septembre 2026, poursuit le rythme de publication semestriel de Java en tant que deuxième version non-LTS suivant Java 25. Bien que Java 25 demeure la version actuelle avec support à long terme (LTS), Java 27 apporte des améliorations significatives en matière d’efficacité mémoire, de ramasse-miettes (Garbage Collection), de sécurité, d’observabilité et d’expressivité du langage.
Cette version comprend 9 JEPs : 4 finalisées, 4 en preview et 1 en incubation. Dans cet article, nous explorerons les nouvelles fonctionnalités de Java 27, en mettant un accent particulier sur les JEPs finalisées et leur impact sur le développement Java.
Note : Téléchargez OpenJDK 27 ici : https://jdk.java.net/27/
JVM
JEP 523 : Make G1 the Default Garbage Collector in All Environments
G1 est le ramasse-miettes par défaut de Java depuis Java 9, mais pas tout à fait partout. Jusqu’à Java 26, la JVM HotSpot basculait automatiquement sur le Serial GC lors de l’exécution dans des environnements contraints disposant d’un seul CPU ou de moins de 1 792 Mo de mémoire physique.
Ce comportement avait du sens lors de l’introduction de G1 en tant que valeur par défaut. Le Serial GC possède une implémentation très simple et offrait historiquement un meilleur débit ainsi qu’une empreinte mémoire plus faible sur les machines aux ressources limitées.
Cependant, G1 a considérablement évolué depuis Java 9. Son empreinte mémoire native a été réduite, et de récentes améliorations ont progressivement comblé l’écart de débit avec le Serial GC. Dans Java 26, la JEP 522 a notamment supprimé le surcoût de synchronisation des barrières d’écriture de G1 en introduisant une seconde table de cartes (card table), offrant ainsi des gains de débit importants.
Avec la JEP 523, Java 27 parachève cette évolution : G1 est désormais le ramasse-miettes par défaut dans tous les environnements, quel que soit le nombre de CPU disponibles ou la quantité de mémoire physique.
Le Serial GC n’est pas supprimé pour autant. Les applications qui bénéficient de ses caractéristiques peuvent toujours le sélectionner explicitement :
java -XX:+UseSerialGC -jar application.jar
De même, les applications qui sélectionnent déjà explicitement G1, ZGC, Parallel GC, Shenandoah ou un autre collecteur disponible ne sont pas impactées.
JEP 534 : Compact Object Headers by Default
La JEP 534 fait des en-têtes d’objets compacts (Compact Object Headers) la disposition d’en-tête par défaut dans la JVM HotSpot 64 bits.
Les en-têtes d’objets compacts font partie du Projet Lilliput, dont l’objectif est de réduire l’empreinte mémoire des objets Java en réduisant la taille de leurs en-têtes de 96 bits à 64 bits sur les architectures 64 bits.
J’ai déjà rédigé un article d’analyse approfondie dédié au Projet Lilliput, à la disposition mémoire des objets Java et à la JEP 519, dans lequel j’explique en détail comment les objets Java sont représentés en mémoire, comment fonctionnent les en-têtes d’objets et comment les en-têtes d’objets compacts peuvent réduire significativement la consommation mémoire.
Avant Java 27, les en-têtes d’objets compacts devaient être activés explicitement :
java -XX:+UseCompactObjectHeaders -jar application.jar
À partir de Java 27, plus aucune configuration n’est requise :
java -jar application.jar
La JVM utilise automatiquement la disposition compacte. Les applications qui doivent revenir à l’ancienne disposition d’en-tête d’objet peuvent toujours désactiver la fonctionnalité explicitement :
java -XX:-UseCompactObjectHeaders -jar application.jar
JEP 536 : JFR In-Process Data Redaction
JDK Flight Recorder (JFR) est l’un des outils les plus utiles pour diagnostiquer les applications Java en production. Il enregistre des informations sur l’utilisation du CPU, le ramasse-miettes, les threads, les allocations, les verrous (locks), les E/S et de nombreux autres événements de la JVM avec un surcoût relativement faible.
Cependant, un enregistrement JFR peut également contenir des informations sur la manière dont la JVM a été démarrée et configurée, notamment les arguments de la ligne de commande, les variables d’environnement et les propriétés système.
Cela peut poser un problème de sécurité, car ces valeurs peuvent contenir des informations sensibles telles que des mots de passe, des clés d’API, des jetons d’accès ou des identifiants.
Par exemple, imaginez démarrer une application comme ceci :
$ export ACCESS_TOKEN=SECRET_TOKEN
$ java -XX:StartFlightRecording:filename=dump.jfr \
-Xmx2G \
-Djavax.net.ssl.keyStorePassword=SECRET_PASSWORD \
-jar application.jar \
--dbpassword ANOTHER_SECRET_PASSWORD
Avant Java 27, ces valeurs sensibles pouvaient apparaître directement dans l’enregistrement JFR via des événements tels que jdk.InitialEnvironmentVariable, jdk.InitialSystemProperty et jdk.JVMInformation.
Cela devient particulièrement problématique lorsque les fichiers .jfr sont partagés avec d’autres développeurs, joints à des tickets de support ou téléversés sur des systèmes externes pour analyse.
La JEP 536 résout ce problème en introduisant la rédaction de données en cours de processus (in-process data redaction).
Au lieu d’écrire des informations sensibles dans l’enregistrement et de nettoyer le fichier après coup, JFR identifie et caviarde désormais les valeurs sensibles avant qu’elles ne soient écrites dans l’enregistrement.
Java 27 introduit deux nouvelles sous-options à -XX:FlightRecorderOptions :
redact-key redact-argument
redact-key est utilisé pour identifier les variables d’environnement et les propriétés système sensibles, tandis que redact-argument s’applique aux arguments de la ligne de commande.
JFR est fourni avec des filtres de rédaction par défaut à la fois pour les arguments de la ligne de commande et pour les paires clé-valeur telles que les variables d’environnement et les propriétés système.
Si ni redact-key ni redact-argument n’est spécifié, ces filtres intégrés sont automatiquement utilisés. Ils couvrent les termes sensibles courants tels que les mots de passe, secrets, jetons (tokens), identifiants, clés privées, clés d’API et secrets clients.
Langage
JEP 532 : Primitive Types in Patterns, instanceof, and switch (Fifth Preview)
La JEP 532 poursuit le travail d’extension du filtrage par motif (pattern matching) de Java aux types primitifs.
Jusqu’à présent, le pattern matching était principalement associé aux types de référence. Cette fonctionnalité permet aux types primitifs de participer également au pattern matching.
Par exemple :
int value = 100;
if (value instanceof byte b) {
System.out.println("Fits in a byte: " + b);
}
Le motif ne correspond que si la conversion est exacte, ce qui signifie qu’aucune information n’est perdue. Par exemple, 100 correspond à un byte, alors que 1000 ne correspond pas.
La fonctionnalité étend également le switch pour prendre en charge tous les types primitifs, y compris long, float, double et boolean :
long value = 42L;
String result = switch (value) {
case 0L -> "zero";
case 42L -> "the answer";
default -> "other";
};
Les motifs primitifs peuvent également être utilisés directement dans les étiquettes case :
Object value = 42;
switch (value) {
case byte b -> System.out.println("byte: " + b);
case int i -> System.out.println("int: " + i);
default -> System.out.println("other");
}
La JEP 532 constitue la cinquième preview de cette fonctionnalité, après les JEP 455, 488, 507 et 530.
Java 27 n’introduit aucun changement de langage par rapport à Java 26 ; la fonctionnalité reste en preview afin de recueillir des retours d’expérience supplémentaires avant sa finalisation.
API
JEP 527 : Post-Quantum Hybrid Key Exchange for TLS 1.3
La JEP 527 renforce TLS 1.3 contre les futures attaques par informatique quantique en introduisant des algorithmes d’échange de clés hybrides.
L’idée est de combiner un algorithme traditionnel à courbes elliptiques avec l’algorithme post-quantique ML-KEM. Cela protège contre la menace du type « intercepter maintenant, décrypter plus tard » (harvest now, decrypt later), où le trafic chiffré est capturé aujourd’hui et potentiellement déchiffré à l’avenir à l’aide d’ordinateurs quantiques.
Java 27 introduit trois schémas hybrides : X25519MLKEM768, SecP256r1MLKEM768 et SecP384r1MLKEM1024.
X25519MLKEM768, qui combine X25519 + ML-KEM-768, est activé par défaut. Les applications utilisant les API standard javax.net.ssl peuvent donc bénéficier d’une protection post-quantique sans modifier leur code, à condition qu’elles ne remplacent pas les groupes nommés TLS par défaut.
Les groupes pris en charge peuvent toujours être personnalisés à l’aide de jdk.tls.namedGroups ou de SSLParameters#setNamedGroups.
La JEP 527 rend ainsi les applications Java plus préparées au post-quantique par défaut, tout en maintenant la compatibilité avec les infrastructures TLS existantes.
JEP 531 : Lazy Constants (Third Preview)
Les constantes paresseuses (Lazy Constants) offrent un moyen simple d’initialiser une valeur uniquement lorsqu’elle est nécessaire pour la première fois, tout en permettant à la JVM de traiter cette valeur comme une véritable constante et d’appliquer des optimisations telles que la propagation de constantes (constant folding).
Exemple :
static final LazyConstant<Logger> LOGGER = LazyConstant.of(Logger::create); Logger logger = LOGGER.get();
Le supplier est évalué au plus une fois avec succès, de manière sécurisée pour les threads (thread-safe), lors du premier appel à get().
Java 27 apporte deux changements principaux par rapport à la preview précédente :
isInitialized()etorElse()sont supprimés.- Les collections paresseuses sont étendues avec
Set.ofLazy(...), aux côtés du support existant desListetMapparesseuses.
La JEP 531 reste une API en preview dans Java 27.
JEP 533 : Structured Concurrency (Seventh Preview)
La concurrence structurée (Structured Concurrency) traite un groupe de tâches concurrentes liées comme une seule unité de travail, simplifiant ainsi l’annulation, la gestion des erreurs et l’observabilité.
En utilisant StructuredTaskScope, les sous-tâches sont créées (forked) et rejointes (joined) au sein d’un périmètre bien défini :
try (var scope = StructuredTaskScope.open()) {
Subtask<String> user = scope.fork(() -> findUser());
Subtask<Integer> order = scope.fork(() -> fetchOrder());
scope.join(); // Attend la fin des sous-tâches
return new Response(user.get(), order.get());
}
Java 27 affine principalement la gestion des exceptions. StructuredTaskScope et Joiner portent désormais le type d’exception que join() peut lever, rendant le contrat explicite au moment de la compilation.
Les joiners standards font désormais lever à join() la classique ExecutionException au lieu de l’exception spécifique à la preview FailedException. Joiner.awaitAll() a également été supprimé.
La JEP 533 reste une API en preview dans Java 27.
JEP 537 : Vector API (Twelfth Incubator)
L’API Vector permet aux développeurs d’exprimer des calculs SIMD directement en Java, permettant à la JVM de les compiler en instructions CPU vectorielles optimisées telles qu’AVX ou NEON.
Par exemple :
var va = FloatVector.fromArray(SPECIES, a, 0); var vb = FloatVector.fromArray(SPECIES, b, 0); var result = va.mul(vb).add(va);
Au lieu de traiter une valeur à la fois, le CPU peut traiter plusieurs valeurs en parallèle à l’aide de registres vectoriels.
La JEP 537 constitue la douzième incubation de l’API et n’introduit aucun changement d’implémentation substantiel par rapport aux versions récentes.
L’API Vector reste en incubation en attendant les fonctionnalités nécessaires du Projet Valhalla. Une fois celles-ci disponibles, l’API devrait passer du statut d’Incubator à celui de Preview.
JEP 538 : PEM Encodings of Cryptographic Objects (Third Preview)
La JEP 538 fournit une API Java standard pour encoder et décoder des clés cryptographiques, des certificats et des CRL au format PEM, évitant ainsi l’analyse et le formatage manuels en Base64.
L’API est principalement articulée autour de PEMEncoder et PEMDecoder :
String pem = PEMEncoder.of().encodeToString(publicKey); PublicKey key = PEMDecoder.of().decode(pem, PublicKey.class);
Les clés privées peuvent également être chiffrées et déchiffrées directement via l’API.
Par rapport à Java 26, les principaux changements sont :
DEREncodableest renommé enBinaryEncodable.PEMest désormais une classe ordinaire au lieu d’un record.EncryptedPrivateKeyInfopermet désormais de récupérer unKeyPair.- Une nouvelle exception
CryptoExceptionreprésente les échecs de traitement cryptographique.
La JEP 538 reste une API en preview dans Java 27.
Conclusion
Java 27 poursuit l’évolution constante de la plate-forme en mettant l’accent sur la performance, l’efficacité mémoire, la sécurité et la productivité des développeurs.
Cette version rend plusieurs améliorations importantes disponibles par défaut, notamment les en-têtes d’objets compacts, G1 comme ramasse-miettes par défaut dans tous les environnements, une sécurité TLS post-quantique renforcée et des enregistrements JFR plus sûrs.
Dans le même temps, des fonctionnalités telles que la concurrence structurée, les constantes paresseuses, les motifs primitifs, les API PEM et l’API Vector continuent de mûrir à travers les phases de preview et d’incubation.
Java 27 n’est pas une version LTS, mais elle montre clairement la direction prise par la plate-forme : une JVM plus efficace, des paramètres de sécurité par défaut plus stricts et un modèle de programmation plus simple pour les applications Java modernes.
Java 27 est-elle une version avec support à long terme (LTS) ?
Non, Java 27 est une version standard disposant de 6 mois de support. La version LTS actuelle reste Java 25. Java 27 est idéale pour tester les améliorations de performances et les nouvelles fonctionnalités avant la prochaine version LTS.
Quel est l’impact principal des en-têtes d’objets compacts (JEP 534) ?
Les en-têtes d’objets compacts réduisent la taille des en-têtes d’objets de 96 bits à 64 bits sur les architectures JVM 64 bits. Cela réduit l’empreinte mémoire par défaut sans nécessiter d’options JVM explicites dans Java 27.
Pourquoi le GC G1 est-il désormais activé dans les environnements contraints (JEP 523) ?
L’empreinte mémoire et le débit de G1 se sont nettement améliorés au fil des récentes versions. Le Serial GC n’est plus déclenché automatiquement sur les systèmes mono-CPU ou à faible mémoire, bien qu’il reste disponible via -XX:+UseSerialGC.
Comment fonctionne la rédaction de données en cours de processus de JFR (JEP 536) ?
JFR caviarde les paramètres sensibles (tels que les mots de passe, clés et jetons) directement en mémoire avant de les écrire dans l’enregistrement .jfr, évitant ainsi les fuites accidentelles lors du partage de journaux de diagnostic.
Dois-je mettre à jour mon code pour utiliser TLS 1.3 Post-Quantique (JEP 527) ?
Non. L’algorithme d’échange de clés hybride X25519MLKEM768 est activé par défaut pour les connexions TLS 1.3, offrant une sécurité résistante au quantique dès l’installation pour les applications TLS Java standard.