Pourquoi faut-il passer de Java 11 à Java 17?

Introduction

Java 17 fraichement sorti, et étant la nouvelle version LTS (Long Term Service) d’Oracle après Java 11, on est en mesure de se poser la question de savoir s’il est intéressant et nécessaire de passer de Java 11 à Java 17. Je suis persuadé que beaucoup de développeurs, lead techniques et architectes se sont posés cette question.

Pour essayer d’y répondre, il faut déjà savoir ce que contiennent les versions intermédiaires, évaluer leurs contenues et les bénéfices qu’ils peuvent apporter sur nos différents projets et finalement évoquer les risques encourus en terme de stabilité ou de fonctionnalités expérimentales et/ou dépréciés.

Je vous propose de parcourir les différentes JEP (JDK Enhanced Proposal) embarqués dans les releases. Le but ici n’est pas d’être exhaustif à 100% sur tous les changements, notamment je ne trace pas l’ensemble des bugs corrigés ni toutes les améliorations mineures. Ceci afin de ne pas rendre cet article indigeste. On va donc se concentrer principalement sur les JEP. Le détail de chaque JEP peut se trouver facilement sur internet, je vous laisse libre de chercher et consulter pour de plus amples détails.

Roadmap

Avant toute chose, un rappel des dates importantes :

  • Sortie
    • Java 11 : septembre 2018
    • Java 17 : septembre 2021
  • Support :
    • LTS Java 11 cours jusqu’à septembre 2023 (avec extension possible jusqu’à septembre 2026)
    • LTS Java 17 cours jusqu’à septembre 2026 (avec extension jusqu’à septembre 2029)

source : https://www.oracle.com/java/technologies/java-se-support-roadmap.html

Évolution du langage

Java a introduit plusieurs nouveautés dans la sémantique et les fonctionnalités du langage (17 JEPs au total). Nous noterons les éléments suivants :

  • Switch Expressions | Pattern Matching (nouveau mot clé « yield ») : JEP-325, JEP-354, JEP-361, JEP-406
  • Text Blocks : JEP-355, JEP-368, JEP-378
  • Pattern Matching pour instanceof : JEP-305, JEP-375, JEP-394
  • Records : JEP-359, JEP-384 (intégration avec les Sealed Classes), JEP-395
  • Sealed Classes : JEP-360, JEP-397, JEP-490 – nouveaux mots clés « sealed », « non-sealed » et « permits »
  • Hidden Classes : JEP-371

Évolution de la JVM

De grosses évolutions ont été apportées à la JVM et à ses différents garbage collectors (16 JEPs).

  • améliorations significatives sur le temps de démarrage de la JVM
  • évolutions Garbage Collectors :
  • Shenandoah
    • nouveau garbage collector low-latency : JEP-189, JEP-379
  • G1
    • amélioration des performances et gestion mémoire : JEP-344, JEP-346
    • NUMA-Aware Memory Allocation : JEP-345
  • ZGC
    • Concurrent Thread-Stack Processing : JEP-351, JEP 377, JEP-376
    • ajout du GC ZGC sur macOS et Windows : JEP-364, JEP-365
  • Parallel GC
    • diverses corrections de bug qui boostent les performances
  • évolutions gestion mémoire
    • Default and Dynamic CDS Archives : JEP-341, JEP-350
  • supprimés / dépréciés
    • dépréciation du ParallelScavenge + SerialOld GC Combination : JEP-366
    • désactivation et dépréciation du Biased Locking : JEP-374
    • suppression de Pack200 Tools et API (déprécié depuis java 11) : JEP-367
    • suppression du GC Concurrent Mark Sweep (CMS) : JEP-363

Nouvelles ou refonte d’API

Il y a également du nouveau du côté des API, que ce soit en termes de refontes de l’existant (par soucis de maintenabilité ou performance) ou de nouvelles fonctionnalités (14 JEPs) :

  • nouvelles API
    • Microbenchmark Suite : JEP-230
    • Vector API – nouvelle API pour du calcul vectoriel : JEP-338, JEP-414
    • Foreign Linker API – nouvelle API pour les appels vers du code natif (comme du C) : JEP-389
    • Enhanced Pseudo-Random Number Generators : nouvelle interface RandomGenerator et la factory RandomGeneratorFactory. Ajout de nouveaux algorithmes de génération de nombres aléatoires : JEP-356
    • Foreign-Memory Access API – API d’accès à la mémoire hors-heap : JEP-370, JEP-383, JEP-393
    • Foreign Function et Memory API : JEP-412
  • refontes d’API
    • JVM Constants API : JEP-334
    • réimplémentation de la Legacy Socket API : JEP-353
    • réimplémentation de la DatagramSocket API : JEP-373
    • modification de l’API MappedByteBuffer : JEP-352
    • Context-Specific Deserialization Filters – amélioration des filtres sur la désérialization d’objets : JEP-415

Architecture

L’architecture de Java a subit un petit lifting et plusieurs fonctionnalités ont été dépréciés puis supprimés, mais de nouveaux supports ont été ajoutés par la suite (8 JEPs) :

  • évolutions
    • One AArch64 Port, Not Two : JEP-340
    • Alpine Linux Port : JEP-386
    • Windows/AArch64 Port : JEP-388
    • macOS/AArch64 (aussi connu sous le nom de « Apple Silicon M1 ») architecture : JEP-391
  • dépréciations
    • dépréciation du portage Solaris et SPARC : JEP-362
    • dépréciation de l’API Applet : JEP-398
  • suppressions
    • suppression du Solaris et SPARC : JEP-381
    • suppression du Nashorn JavaScript Engine : JEP-372

Divers / Miscellaneous

Et finalement diverses améliorations sur l’outillage, et des fonctionnalités de second plan (17 JEPs) :

  • Packaging Tool : JEP-343, JEP-392
  • JFR Event Streaming – JDK Flight Recorder : JEP-349
  • Helpful NullPointerExceptions – logs des NPE beaucoup plus précis : JEP-358, JEP-358
  • Edwards-Curve Digital Signature Algorithm (EdDSA) : JEP-339 – nouvel algorithme de crypto
  • RMI Activation :
    • déprécié : JEP-385
    • supprimé : JEP-407
  • Enable C++14 Language Features (JDK source code) : JEP-347
  • Migrate from Mercurial to Git, Migrate to GitHub : JEP-357, JEP-369
  • Unix-Domain Socket Channels : JEP-380
  • Warnings for Value-Based Classes : JEP-390
  • Strongly Encapsulate JDK Internals by Default – securité et maintenabilité du JDK : JEP-396, JEP-403
  • Restore Always-Strict Floating-Point Semantics : JEP-306
  • New macOS Rendering Pipeline : JEP-382
  • dépreciation du Security Manager : JEP-411

Bilan

Les évolutions du langage, même si elles ne sont pas révolutionnaires sont plutôt intéressantes. Notamment pour les cas des Pattern Matching sur le instanceof et le switch. On notera que Java se dote enfin officiellement d’un outillage pemettant d’avoir des logs plus précises sur les NullPointerExceptions, ce qui était très attendu par la communauté des développeurs.

En terme d’évolutions sur la JVM, il y a eu de gros changements, que ce soit en diversités d’implémentation de GC ou de performances sur le chargement du code et la gestion mémoire.
L’un des ingénieurs Oracle travaillant sur l’optimisation de la JVM considère que le démarrage de la JVM (sur une application de base type « Hello World ») prends sur Java 17 en moyenne moins de 40ms, et se pose même la question de savoir si ça vaut le coup de continuer à passer du temps à l’optimisation de cette tâche (https://cl4es.github.io/2020/12/06/Towards-OpenJDK-17.html).
Pour rappel, Java 9 avait introduit la modularité dans le JDK et avec lui des effets de bord qui avaient amenés à un démarrage plus lent de la JVM (autour de 80ms pour la même application).

En parlant de performances, on notera que Java s’est enfin doté d’un outil natif de benchmarking (Microbenchmark Suite depuis Java 12), ce qui a fait et continue de faire le bonheur des plus ferrus sur le sujet.
Plus d’informations sur le sujet ici : https://www.javacodegeeks.com/2021/09/how-much-faster-is-java-17.html

En terme de stabilité de la version, il n’y a pas eu de changements majeurs sur le JDK, mais plutôt une consolidation de ce qui a déjà été apporté à la version 9 et la modularité.
On voit que motivé par ce choix d’architecture, Oracle se lance dans la refonte de certaines API, dont Socket, DatagramSocket et Vector.

Dernier sujet, et non des moindres, directement en lien avec la sortie de Java 17 : Oracle apporte un changement important sur la licence pour les versions d’Oracle JDK LTS : « Oracle No-Fee Terms and Conditions » (NFTC), cf. https://blogs.oracle.com/java/post/free-java-license.
Cette licence donne droit à une utilisation gratuite de la version Java officielle d’Oracle, que ce soit en développement comme en production (jusqu’à au moins 1 an après la sortie de la LTS suivante).
Cette nouveauté n’est pas rétrocompatible et ne s’applique donc qu’à partir de la LTS Java 17. Il n’y a pas de changement pour la version Oracle OpenJDK : elle reste toujours sur la licence GPL.

Il est à noter que Mark Reinhold, le chief Java architect pour le Java Platform Group chez Oracle, propose de passer à des LTS sur des cycles de 2 ans (source : https://www.infoq.com/news/2021/10/oracle-java-two-year-lts/). Ceci pourrait en effet permettre de lancer des nouveautés plus fréquemment et mieux se positionner par rapport aux attentes de la communauté de développeurs.

TL;DR

Sans grande surprise, il est recommandé de passer de Java 11 à Java 17, que ce soit par rapport aux nouveautés du langage apportés comme sur l’amélioration des performances et la stabilité globale.
Le support sur Java 11 s’arrêtant fin 2023, les projets ont encore une marge non négligeable pour basculer, ce qui est une bonne nouvelle pour les plus conservateurs.

Et en guise de dessert, je vous laisse avec un aperçu sur le futur de Java avec la vidéo de la conférence de José Paumard durant le DevFest 2021 : https://devfest2021.gdgnantes.com/sessions/java_au_futur___des_record_au_pattern_matching/.

S’abonner
Notifier de
guest
0 Commentaires
Inline Feedbacks
View all comments