Java 24 : quoi de neuf ?

Java 24 : quoi de neuf ?

Maintenant que Java 24 est features complete (Rampdown Phase One au jour d’écriture de l’article), c’est le moment de faire le tour des fonctionnalités qu’apporte cette nouvelle version, à nous, les développeurs.

Cet article fait partie d’une suite d’article sur les nouveautés des dernières versions de Java, pour ceux qui voudraient les lire en voici les liens : Java 23, Java 22, Java 21, Java 20, Java 19, Java 18, Java 17, Java 16, Java 15, Java 14, Java 13, Java 12, Java 11Java 10, et Java 9.

Java 24 contient par moins de 24 JEP, c’est un record et surtout un chiffre éponyme !

JEP 404: Generational Shenandoah (Experimental)

Shenandoah est un Garbage Collector (GC) initialement développé par RedHat et inclus dans OpenJDK. Il réduit les temps de pause du GC en effectuant le travail d’évacuation en même temps que les threads applicatifs en cours d’exécution.

Jusqu’ici, Shenandoah n’était pas générationnel, ce qui veut dire qu’il ne séparait pas la heap en plusieurs zones contenant des objets d’age différent. Les GC générationnels se basent sur la Weak Generational Hypotesis : most objects die young, comme collecter un objet mort est très peu coûteux, séparer les objets jeunes des objets vieux permet de se focaliser sur les objets jeunes pour nettoyer la heap de manière plus performante.

Tous les GC actuels sont générationnels, même ZGC qui ne l’était pas à ses débuts, mais qui depuis cette release ne supporte plus que le mode générationnel. Shenandoah en ajoutant un mode générationnel en expérimental comble son retard.

Shenandoah est un GC concurrent, cela a un coût en termes d’utilisation de ressources CPU et mémoire, un mode générationnel devrait permettre de mitiger le coût de fonctionnement du GC tout en gardant un objectif de pause de l’ordre de la milliseconde.

Pour activer le mode générationnel, il faut utiliser les options JVM suivantes : -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational.

Plus d’information dans la JEP 404.

JEP 450: Compact Object Headers (Experimental)

Cette JEP provient du projet Liliput dont le but est de réduire la taille du header des objets de 128 bits à 64 bits ou moins. C’est d’ailleurs très exactement ce qu’a délivré la JEP 450 : un mode expérimental pour la JVM qui réduit à 64 bits le header des objets.

Chaque objet en Java a un header, puis de la données : ses attributs. Si vous avez un objet Point(int x, int y), bien qu’un int utilise 32 bits, la taille de l’objet Point va être de 192 bits, car chaque objet stock dans sa référence un ensemble d’information sur 128 bits.

Les premiers 64 bits d’un header sont nommés Mark Word et stockent soit le hash code, l’âge GC et certains flags nécessaire pour la JVM; soit un pointeur vers une structure externe. Les derniers 64 bits sont nommés Class Word et stockent un pointeur vers la classe. Le mode spécial Compressed Class Pointer permet déjà de le réduire à 32 bits, mais sur une architecture 64 bits, l’alignement en mémoire fait que le gain n’est pas forcément présent même si la JVM peut optimiser le layout d’un objet en utilisant ces 32 bits ainsi libérés.

En activant les headers d’objets compacts via les options JVM -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders, la JVM va stocker le header des objets sur 64 bits : 22 bits pour le pointeur de classe, 31 bits pour le hash code, 4 bits réservés pour Valhalla et les bits restant comme précédemment pour l’âge GC et les flags de la JVM.

Des tests préliminaires montrent une utilisation mémoire réduite de 10 à 20 %.

Amazon a réalisé des tests qui montrent que de nombreuses charges de travail bénéficient d’une baisse de l’utilisation CPU pouvant aller jusqu’à 30 %.

Il y a quelques limites à ce mode, il ne peut supporter les heap de plus de 8TB (sauf pour ZGC) et se limite à 4 millions de classes.

Plus d’information dans la JEP 450.

JEP 472: Prepare to Restrict the Use of JNI

La JEP 472 restreint l’utilisation la Java Native Interface (JNI) et ajuste l’API Foreign Function and Memory (FFM) en conséquence.

L’utilisation d’une fonction native générera un WARNING au démarrage de la JVM sauf si l’option JVM --enable-native-access est utilisée pour l’autoriser. Il est aussi possible d’utiliser l’entrée de manifest Enable-Native-Acces.

L’utilisation d’une fonction native sans l’avoir autorisée au préalable est dite illégale, l’option JVM --illegal-native-access permet de contrôler le comportement de la JVM dans ces cas_là. Elle a comme valeur par défaut warn, et peut prendre les valeurs suivantes :

  • allow : l’utilisation est autorisée sans restriction,
  • warn : le défaut en Java 24, un warning sera écrit dans les logs de la JVM,
  • deny : l’utilisation est refusée, une exception IllegalCallerException sera levée.

Exemple de warning généra par la JVM au chargement d’une librairie native si l’accès n’a pas été autorisé :

WARNING: A restricted method in java.lang.System has been called
WARNING: System::load has been called by com.foo.Server in module com.foo (file:/path/to/com.foo.jar)
WARNING: Use --enable-native-access=com.foo to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

Le comportement par défaut de la JVM en cas d’utilisation d’une librairie native passera de warn à deny dans une future release.

Cette JEP fais partie d’une ensemble de changement dans la JVM pour restreinte certaines fonctionnalités de la JVM par défaut, en forçant l’utilisateur à activer spécifiquement ces fonctionnalités, dans le but d’avoir une JVM plus robuste. Vous pouvez en lire plus sur le sujet dans la JEP en draft Integrity by Default.

Plus d’information dans la JEP 472.

JEP 475: Late Barrier Expansion for G1

La JEP 475 simplifie la mise en place des barrières du Garbage Collector (GC) G1 en déplaçant leur expansion du début du pipeline de compilation du Just In Time (JIT) compiler de la JVM (C2) vers la fin.

G1 utilise des barrières pour enregistrer des informations sur les accès à la mémoire de l’application. Ces barrières nécessitent une interaction avec le JIT et en complexifient le code et la maintenance.

Des tests préliminaire ont montré que la mise en place des barrières G1 avait un overhead de 10 à 20% sur le JIT. L’idée est qu’au lieu d’injecter la barrière au début de la phase de compilation (dans l’IR – l’intermediate representation du code à compiler) et de laisser C2 compiler le code de la barrière, il est plus intéressant de l’injecter à la fin de la phase de compilation directement en assembleur.

Plus d’information dans la JEP 475 ainsi que dans l’article When should a compiler expand garbage collection barriers? de Roberto Castañeda Lozano.

JEP 478: Key Derivation Function API (Preview)

Nouvelle API pour les fonctions de dérivation de clés (Key Derivation Function – KDF), qui sont des algorithmes cryptographiques permettant de dériver des clés supplémentaires à partir d’une clé secrète et d’autres données.

KDF fait partie du standard de cryptographie PKCS #11.

KDF est aussi une des briques nécessaires pour l’implémentation de l’Hybrid Public Key Encryption (HPKE) qui est un algorithme de cryptographie post-quantique. La cryptographie post-quantique regroupe un ensemble d’algorithme cryptographique qui sont résistants aux ordinateurs quantiques. Je reviendrai sur le sujet dans la section traitant des algorithmes de type Module-Lattice-Based via les JEP 496 et 497.

Plus d’information dans la JEP 478.

JEP 479: Remove the Windows 32-bit x86 Port

Le port de la JVM pour Windows 32-bit pour les architectures x86 a été déprécié en Java 21, il sera supprimé en Java 24.

Plus d’information dans la JEP 479.

JEP 483: Ahead-of-Time Class Loading & Linking

Le but de cette nouvelle fonctionnalité est d’améliorer le temps de démarrage de la JVM en rendant les classes d’une application instantanément disponibles, dans un état chargé et lié, lorsque la JVM démarre.

Pour cela, un premier lancement de l’application est nécessaire. Lors de ce lancement, les classes chargées sont enregistrées dans un cache pour être disponibles immédiatement lors de lancements successifs.

Dans la JVM, les classes sont chargées à la demande via un ClassLoader. La JVM est dynamique, la liste des classes à charger n’est pas fixe au démarrage, car des classes peuvent être créées dynamiquement (par exemple : via des proxies dynamiques), ou chargées dynamiquement via réflexion.

Mais charger une classe à un coût :

  • La JVM doit scanner tous les JAR du classpath pour localiser la classe et charger le fichier .class en mémoire,
  • Puis elle doit parser la classe et créer un objet Class qui la représente, linker la classe, vérifier le bytecode, résoudre les références…
  • Et pour finir, elle doit exécuter les initializers statique et les blocks statique.

Même si ces étapes sont optimisées, une application qui utilise des centaines de JAR et qui initialise des milliers de classes peut prendre pas mal de temps au démarrage dû à ces phases, ce qui est encore plus problématique pour les frameworks de microservice comme Spring qui ont tendances à scanner des milliers de beans au démarrage. Même quand ces étapes sont faites de manière paresseuse, à la demande, elles impactent fortement les premières minutes de fonctionnement d’une application menant à une performance en pic tardive.

Avec la JEP 483: Ahead-of-Time Class Loading & Linking, il va être possible de créer un cache des classes initialisées et linkées, puis de l’utiliser dans une exécution successive de l’application pour en optimiser le démarrage.

Contrairement à GraalVM qui propose le même type de fonctionnalité, mais dans un monde clôt, toutes les fonctionnalités de la JVM sont préservées. Une classe qui n’est pas présente dans l’archive sera chargée dynamiquement par la JVM.

L’utilisation du mode AOT se fait en trois étapes : enregistrement des classes à inclure dans le cache, création du cache, puis utilisation du cache.

Exemple avec une application de type Hello World dans une classe unique Main :

  1. java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf Main : lacement de l’application en mode record pour enregistrer les classes à charger dans un fichier de configuration app.aotconf.
  2. java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:AOTCache=main.aot : utilisation du fichier de configuration app.aotconf pour créer une archive de cache main.aot.
  3. java -XX:AOTCache=main.aot Main : lancement de l’application avec le cache main.aot.

Une application telle que Spring PetClinic charge et lie environ 21 000 classes au démarrage et démarre en 4,486 secondes (JDK 23). Avec un cache AOT, elle démarre en 2,604 secondes – ce qui représente une amélioration de 42 %. Le cache AOT occupe 130 mégaoctets.

Plus d’information dans la JEP 483.

JEP 486: Permanently Disable the Security Manager

Le Security Manager a été déprécié en Java 17, il est maintenant supprimé totalement du JDK !

Le Security Manager était un composant compliqué à maintenir avec une empreinte importante dans le code, et certainement un impact en termes de performance (au moins au démarrage d’une application jusqu’à ce que le JIT en optimise les appels) ; sa suppression a entraîné la suppression de plus de 14000 lignes de code !

Il y a eu beaucoup de discussion autour de sa suppression, le Security Manager permettait une forme de sécurité via des checks réalisés lors de l’appel de certaines méthodes du JDK (ouverture de thread, accès fichiers…), il avait été créé au départ pour sécuriser l’appel de code non fiable (par exemple, du code externe exécuté dynamiquement) entre autres pour les applets (qu’elles reposent en paix). Hors les besoins modernes de sécurité sont plus complexes et doivent être réalisés via un ensemble d’outils dont la sécurité périphérique et le sandboxing sont les principaux alliés. Il est fortement déconseillé d’exécuter du code non fiable, et si cela est nécessaire d’autres techniques doivent être mises en oeuvres.

Ce qui est dommage dans la suppression du Security Manager c’est que même imparfait, il rendait de nombreux services, entre autres pour les plateformes qui avaient un système de plugin tel que Kafka Connect, Elasticsearch ou Kestra – l’orchestrateur de donnée pour lequel je travaille. Un système de plugin va par définition exécuter du code non fiable, et les autres techniques qui doivent être mises en oeuvres ne sont pas fournies en remplacement du Security Manager. La JEP conseille d’exécuter du code non-fiable dans une sandbox (Docker, GraalVM) ou d’implémenter des contrôles d’accès via un agent Java !

Pour moi, c’est assez problématique de supprimer sans aucune solution le Security Manager, il permettait de sécuriser du code non fiable, ce qui est nécessaire pour un système de plugin. Une partie de ses fonctionnalités auraient pu être préservées ou remplacées par un système plus simple. Bien sûr, je suis ici biaisé car je vais devoir ré-implémenter les règles de sécurité de Kestra autrement, car nous utilisions le Security Manager.

Stuart Marks a écrit un article intéressant sur la suppression du Security Manager : Detoxifying the JDK Source Code.

Plus d’information dans la JEP 486.

JEP 490: ZGC: Remove the Non-Generational Mode

ZGC est un Garbage Collector (GC) développé par Oracle et inclus dans OpenJDK. Il réduit les temps de pause du GC en effectuant le travail d’évacuation en même temps que les threads applicatifs en cours d’exécution.

ZGC n’était pas générationnel lors de sa création, mais a un mode générationnel depuis Java 21. Cette JEP va supprimer le mode non générationnel pour réduire le coût de maintenance de ZGC.

Plus d’information dans la JEP 490.

JEP 491: Synchronize Virtual Threads without Pinning

Les Virtual threads sont des threads légers, avec un coût de création et de scheduling faible, qui permettent de faciliter l’écriture d’application concurrente. Un virtual thread, quand il s’exécute, va être monté sur un platform thread (thread OS).

Jusqu’ici, la synchronisation Java (via le mot clé synchronized) ne lâchait pas le platform thread, on disait alors que le platform thread était attaché (pinned en anglais) au virtual thread, ce qui limitait grandement la scallabilité des virtual threads si beaucoup d’opérations de synchronisation étaient effectuées. Et la synchronisation est utilisée à de nombreux endroits au sein du JDK (pour les I/O par exemples), ainsi que dans de nombreuses librairies (clients JDBC par exemple).

Avec la JEP 491, les virtual threads vont maintenant lâcher leur platform thread en cas de synchronisation. C’est une étape importante pour les virtual threads, car c’était le principal souci de performance qu’on pouvait rencontrer lors de leur utilisation.

Plus d’information dans la JEP 491.

JEP 493: Linking Run-Time Images without JMODs

JEP 493 réduit la taille du JDK d’environ 25 % en permettant à l’outil jlink de créer des images d’exécution personnalisées sans utiliser les fichiers JMOD du JDK. Cette fonction doit être activée lorsque le JDK est construit, tous les fournisseurs de JDK pourraient ne pas l’activer, mais il est probable qu’ils le fassent et que le JDK 24 soient 25% plus petit que les précédentes versions !

Les fichiers JMOD sont les fichiers des modules du JDK utilisés par jlink pour créer une image du JDK; or cette image contient elle-même les fichiers des modules du JDK qui sont donc dupliqués, les fichiers JMOD ne servant à rien.

Plus d’information dans la JEP 493.

JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism

La JEP 496 fournit une implémentation du mécanisme d’encapsulation de clés basé sur un module-réseau (Module-Lattice en anglais) résistant aux algorithmes quantiques (ML-KEM). Les mécanismes d’encapsulation de clés (KEM) sont utilisés pour sécuriser les clés symétriques sur des canaux de communication non sécurisés à l’aide de la cryptographie à clé publique. Le ML-KEM a été normalisé par le National Institute of Standards and Technology (NIST) des États-Unis dans le cadre de la norme FIPS 203.

Les algorithmes de type module-réseau sont une classe d’algorithme dit post-quantique, ils sont conçus pour être sécurisé contre les futures attaques de l’informatique quantique.

Les algorithmes cryptographiques actuels font appel à des problèmes de mathématiques finies (comme la factorisation des grands nombres) qui sont coûteux en termes de calcul. Casser via brute force ce type d’algorithme pour des clés de grande taille prendrait des milliers d’années, même pour un supercalculateur.

Les ordinateurs quantiques sont théoriquement capables de factoriser de grand nombre de manière beaucoup plus rapide grâce à l’algorithme de Shor, pour sécuriser les communications dans un monde où un ordinateur quantique existerait avec un nombre de Qubit suffisant pour factoriser un grand nombre (il faudrait un nombre de Qubit deux fois supérieur à la taille de la clé), il faut une nouvelle classe d’algorithmes qui se basent sur une preuve mathématique différente, c’est là qu’entre en jeux les algorithmes de type module-réseau.

Le NIST conseille de mettre en place ces algorithmes d’ici 10 ans, mais il faut savoir que pour l’instant les ordinateurs quantiques sont loin d’avoir le nombre de Qubit nécessaire. À ce jour, ils ont généralement au plus 64 Qubit alors qu’il en faudrait 1024 pour casser une encryption 512 bits et 4096 pour une encryption 2048 bits. Sans parler des problèmes d’exactitude…

Plus d’information sur la cryptographie post quantique dans cet article de Ben Evans : Post-Quantum Cryptography in Java.

Plus d’information dans la JEP 496.

JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm

La JEP 497 fournit une implémentation d’algorithme de signature numérique basé sur le module-réseau (Module-Lattice en anglais) résistant aux algorithmes quantiques (ML-DSA). Les signatures numériques sont utilisées pour détecter les modifications non autorisées des données et pour authentifier l’identité des signataires. Il a été normalisé par le National Institute of Standards and Technology (NIST) des États-Unis dans la norme FIPS 204.

Plus d’information dans la JEP 497.

JEP 498: Warn upon Use of Memory-Access Methods in sun.misc.Unsafe

Unsafe est, comme son nom l’indique, une classe interne et non supportée du JDK qu’il n’est pas sans danger d’appeler. Pour des raisons historiques, de nombreux frameworks bas-niveau utilisaient Unsafe pour des accès mémoire plus rapide. Grâce aux fonctionnalités VarHandle API (JEP 193, depuis Java 9) et Foreign Function & Memory API (JEP 454, depuis Java 22), il y a maintenant des remplacements pour les méthodes d’Unsafe accédant à la mémoire qui sont aussi performants, mais plus sûr et supporté.

Toutes ces méthodes ont été dépréciées pour suppression dans Java 23, elles sont à présent modifiées pour générer un WARNING dans les logs de la JVM lors de leur première utilisation.

Ce changement était prévu et annoncé lors de leur dépréciation en Java 23, il est prévu de les dégrader pour lever une exception en Java 26.

Plus d’information dans la JEP 498.

JEP 501: Deprecate the 32-bit x86 Port for Removal

Le port 32-bit pour Windows est supprimé dans cette release, mais il reste un port 32-bit pour d’autres OS (Linux). Cette JEP va déprécier tous les ports 32-bit pour architecture x86 restant, donc celui pour Linux qui est le seul encore supporté. Elle ne porte pas sur les autres ports 32-bit tel que celui pour ARM32 qui n’est pas déprécié. L’industrie a depuis longtemps abandonné l’architecture 32-bit x86, Debian planifiant aussi d’en arrêter le support, il est logique d’en planifier l’arrêt du support dans la JVM.

Pour les architectures non supportées, il existe un port de la JVM sans spécificité d’architecture : le port Zero, qui permettra toujours de faire tourner une JVM sous architecture 32-bit x86.

Plus d’information dans la JEP 501.

Les fonctionnalités qui sortent de preview

Les fonctionnalités suivantes sortent de preview (ou du module incubator) et passent en standard :

  • JEP 484Class-File API : API standard pour parser, générer et transformer les fichiers de classe Java.
  • JEP 485Stream Gatherers : Enrichit l’API Stream avec le support d’opérations intermédiaires personnalisées.

Pour les détails sur celles-ci, vous pouvez vous référer à mes articles précédents.

Les fonctionnalités qui restent en preview

Les fonctionnalités suivantes restent en preview (ou en incubator module) :

  • JEP 487Vector API : neuvième incubation, API permettant d’exprimer des calculs vectoriels qui se compilent au moment de l’exécution en instructions vectorielles pour les architectures CPU prises en charge. Quelques changements dans l’API et des améliorations de performance. Une nouvelle classe Float16 a été ajoutée qui supporte les variables 16-bit au format IEEE 754 binary16 en utilisant la Vector API. Il a été acté dans la JEP que la Vector API sera en incubation tant que les fonctionnalités du projet Valhalla ne seront pas disponibles en preview. Ce qui était attendu, car la Vector API pourra alors tirer parti des améliorations de performance et de représentation en mémoire que devrait apporter le projet Valhalla.
  • JEP 495Simple Source Files and Instance Main Methods : quatrième preview, précédemment nommée Implicitly Declared Classes and Instance Main Methods, simplifie l’écriture de programmes simple en permettant de les définir dans une classe implicite (sans déclaration) et dans une méthode d’instance void main(). Aucun changement.
  • JEP 499Structured Concurrency : quatrième preview, nouvelle API permettant de simplifier l’écriture de code multi-threadé en permettant de traiter plusieurs tâches concurrentes comme une unité de traitement unique. Aucun changement.
  • JEP 487Scoped Values : quatrième preview, permettent le partage de données immuables au sein et entre les threads. Les méthodes ScopedValue.callWhere() et ScopedValue.runWhere ont été supprimées, on ne peut dorénavant utiliser une ScopedValue que depuis call(Callable) ou run(Runnable).
  • JEP 492Flexible Constructor Bodies : troisième preview, fonctionnalité qui autorise des instructions avant l’appel du constructeur parent tant que celles-ci n’accèdent pas à l’instance en cours de création. Aucun changement.
  • JEP 494Module Import Declarations : seconde preview, permet l’import de toutes les classes d’un module, transitivement, via l’instruction import module java.base;. Changements mineurs.
  • JEP 488Primitive Types in Patterns, instanceof, and switch : seconde preview, ajoute le support des types primitifs dans les instanceof et les switch, et enrichit le pattern matching pour supporter des patterns de types primitifs : dans les instanceof, dans les cases des switch, et dans la déconstruction d’un record. Aucun changement.

Pour les détails sur celles-ci, vous pouvez vous référer à mes articles précédents.

Divers

Divers ajouts au JDK :

  • Console.println() : écrit une ligne vide dans une console.
  • Console.readLn() : lit une ligne de texte depuis une console.
  • IO.println() : écrit une ligne vide dans la console système.
  • IO.readLn() : lit une ligne de texte depuis la console système.
  • Reader.of(CharSequence) : renvoie un lecteur qui lit les caractères d’une CharSequence. Le lecteur est initialement ouvert et la lecture commence au premier caractère de la séquence.
  • Process.waitFor(Duration) : fait attendre le thread actuel, si nécessaire, jusqu’à ce que le processus représenté par cet objet Process se termine, ou que la durée d’attente spécifiée s’écoule.

La totalité des nouvelles API du JDK 24 peuvent être trouvées dans The Java Version Almanac – New APIs in Java 24.

Des changements internes, de la performance, et de la sécurité

Comme toutes les nouvelles versions de Java, OpenJDK 24 contient son lot d’optimisation de performance et d’amélioration de sécurité.

  • La suite de cipher TLS_RSA a été désactivée.
  • Les performances pour SHA3 ont été améliorées de 10 à 15% (JDK-8333867).
  • La concaténation de String a été optimisée en utilisant des classes cachées générées via Classfile API et utilisant l’API MethodHandle (JDK-8336856) apportant près de 40% d’optimisation de performance. Voir cet excellent talk de Claes Redestad pendant Devoxx 2024 sur le sujet : https://www.youtube.com/watch?v=tgX38gvMpjs.
  • secondary_super_cache est un cache utilisé pour les instanceof, il met en cache un super type d’une classe. Comme il ne contient qu’une seule entrée, si plusieurs threads font des instanceof sur des super type différentes pour la même classe, le cache va être invalidé sans arrêt, ce qui peut avoir des conséquences importantes en termes de performance. Ce cache a été réécrit par Andrew Haley de chez RedHat qui l’a remplacé par un cache via table de hachage (voir #18309. Ce problème était nommé type pollution; RedHat avait développé un agent Java pour en détecter les cas problématiques (voir type-pollution-agent) et certains frameworks avait même implémenté des solutions de contournement pour l’éviter dans les chemins critiques (par exemple pour Quarkus : #28834, #28985 ou #29109).

JFR Events

Voici les nouveaux événements Java Flight Recorder (JFR) de la JVM :

  • NativeMemoryUsageTotalPeak : Total des pics d’utilisation de la mémoire native pour la JVM (GraalVM Native Image uniquement). Il peut ne pas être la somme exacte des événements NativeMemoryUsagePeak en raison du timing.
  • NativeMemoryUsagePeak : Utilisation maximale de la mémoire native pour un type de mémoire donné dans la JVM (GraalVM Native Image uniquement).
  • SerializationMisdeclaration : Méthodes et champs mal déclarés pour la sérialisation.
  • SwapSpace : mémoire swap de l’OS.

Vous pouvez retrouver tous les événements JFR supportés dans cette version de Java sur la page JFR Events.

Conclusion

Java 24 contient beaucoup de nouveautés, on eut se réjouir de voir les Stream Gatherer sortirent de preview, mais il reste beaucoup de fonctionnalités qui semblent bloquées en preview sans aucun changement.

Personnellement, je suis un peu déçu de la suppression sans remplacement du Security Manager, même si cela va me donner l’opportunité de jouer avec les agents Java très prochainement pour le remplacer ;).

Pour retrouver tous les changements de Java 24, se référer aux release notes.

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.