logo le blog invivoo blanc

JAVA 16 & 17 : Évolutions et nouveautés – Partie 2

8 décembre 2021 | Java | 0 comments

“Java 17 est déjà là ! Euh…on va encore migrer ? Quelle version choisir ? Migrer vers Java X ou vers la dernière version LTS ?”

Les développeurs doivent se tenir informés des nouveautés du langage pour en tirer le meilleur parti en tant que professionnels de l’IT.

Dans la première partie de cet article, nous vous expliquions les évolutions et nouveautés de JAVA 16. Dans cette seconde partie nous abordons les évolutions et nouveautés de JAVA 17.

JAVA 17

1. Pattern Matching pour switch (en preview)

Cette fonctionnalité, introduite en préversion dans jdk 17, intègre le pattern matching dans les switchs. On peut dorénavant faire un switch sur le type d’une variable (y compris enum, record et tableau).
En plus du pattern matching, le switch a été également enrichi pour permettre d’inclure une condition au CASE et de gérer un case spécial null; il est à noter qu’avant java 17, une variable de switch nulle entraînait un NullPointerException.

Exemple :

switch(obj) { 
         
case null -> System.out.println("obj is null");
         
case Integer i -> System.out.println("obj is an integer");
             
case String s ->System.out.println("obj is a string");              
         
case Car c && c.getNoOfWindows() > 4 -> System.out.println("obj is a limousine");
 
case Car c -> System.out.println("obj is a regular car");         
 
default -> System.out.println("obj is another data type");

}

 2. Classe Scellée (Sealed Class)

Les classes scellées (sealed class) permettent de contrôler votre hiérarchie d’héritage.

Veuillez noter que c’est une fonctionnalité en preview dans Java 16, bien qu’elle soit finalisée dans Java 17 (fonctionnalité standard). Vous devez passer l’option–enable-preview lors de l’invocation du compilateur et à l’invocation de la JVM afin d’utiliser cette fonctionnalité avec Java 16.

On utilise souvent cette fonctionnalité quand on veut empêcher les autres classes d’hériter de la classe scellée et qu’on ne veut pas utiliser le mot clé final ni réduire la visibilité de la classe. Seules les classes définies après le mot clé permits sont autorisées à étendre la classe scellée.

Exemple :

sealed interface Vehicle permits Car, Motorbike {}

record Car (String model, String vendor, String color, int price) implements Vehicle { }

record Motorbike (String model, String vendor, String color, int price) implements Vehicle { }

La liste permits signifie que seuls Car et Motorbike peuvent implémenter Vehicle. Toute autre classe ou interface qui tente d’étendre Vehicle recevra une erreur de compilation ou d’exécution.

record Bus (String model, String vendor, String color, int price) implements Vehicle { }
//this doesn’t work

3. Générateurs de nombres pseudo-aléatoires

JDK 17 intègre une nouvelle interface RandomGenerator, et une factory RandomGeneratorFactory, qui fournissent de nouvelles implémentations de générateur de nombre aléatoire, plus sécurisées et plus performantes (attention ils ne sont plus thread-safe). Les anciens générateurs tels que : Random, SecureRandom, SplittableRandom, ThreadLocalRandom implémentent dorénavant cette interface qui ajoute par ailleurs l’accès à un stream de nombre aléatoire (RandomGenerator::doubles(), RandomGenerator::ints(), …).

4. Encapsulation stricte des classes internes du JDK

Certains modules et APIs internes ont été introduits dans Java 9 pour offrir un moyen uniforme d’effectuer les tâches les plus couramment utilisées. Pour décourager les développeurs à utiliser ces classes internes, des avertissements (warnings) de type –illegal access sont générés.

Des arguments de ligne de commande ont également été temporairement ajoutés pour contourner cette restriction –illegal-access=permit.

Concrètement, le mode d’encapsulation était passé de –illegal-access=permit en Java 15 à –illegal-access=deny en Java 16 avec la possibilité de changer l’option de configuration. Avec Java 17, –illegal-access disparaît et l’accès aux classes internes du JDK (hors Unsafe) n’est plus possible.

5. Dépréciations et suppressions

  •  Dépréciation API Applet:
    Historiquement, l’API Applet permet aux développeurs  d’intégrer des animations ou des contrôles Java AWT/Swing dans une page Web. Sauf que de nos jours, aucun navigateur moderne ne prend cela en charge, ce qui implique que les applets ont été essentiellement inaccessibles au cours de la dernière décennie d’où la dépréciation de l’API pour suppression.
  • Dépréciation Security Manager
    La dépréciation la plus importante dans JDK 17 concerne le gestionnaire de sécurité (Security Manager) utilisé depuis Java 1.0 pour restreindre ce que Java pouvait faire localement sur la machine (accès aux réseaux, fichiers…). Initialement, il a été créé pour sécuriser les applets qui, par définition, exécutent du code untrusted, et n’a donc plus de sens dans une JVM qui ne contiendrait plus l’API Applet.
  • Suppressions
  • RMI Activation
  • Experimental AOT and JIT Compiler
  • Changes to javadoc
  • Changes to Oracle JDK license
  • LTS every 2 years
  • Changes to G1 and Parallel GCs
  • Finalizing the Foreign APIs

6. API vectorielle

L’API vectorielle du module incubateur (dk.incubator.vector.Vector<E> et sous classes) permet aux développeurs de définir un calcul vectoriel que le compilateur JIT convertira ensuite en une instruction vectorielle compatible avec l’architecture CPU sur laquelle la JVM s’exécute éliminant ainsi la nécessité de maintenir et d’écrire plusieurs implémentations spécifiques aux plates-formes au sein de la JVM.

Cette fonctionnalité, introduite dans java 16 et continuée dans java 17, peut être utilisée dans les domaines suivants : machine learning,algèbre linéaire, cryptographie, finance et la jdk même.

7. Fonction étrangère et API mémoire (incubation)

Il s’agit d’une évolution et d’une fusion de deux autres modules incubateurs de Java 16 qui sont l’API d’édition de liens étrangers Foreign Linker API (JEP 389) et lAPI d’accès à la mémoire étrangère Foreign Memory API (JEP 393).

L’ API Foreign Function & Memory:

  • Fournit l’accès à la mémoire et permet d’accéder directement aux adresses, segments, layout mémoire…
  • Permet de faire des appels depuis java vers le langage natif et vice versa

Fournit un support pour le langage C (x64 & AArch64) avec une possibilité d’étendre (C++, x86, …)

8. Sémantique à virgule flottante toujours stricte

Par défaut, les calculs sur les nombres de type double ou float sont effectués d’une façon non stricte dans une classe, une interface ou une méthode.

Afin de rendre les opérations en virgule flottante systématiquement strictes, dans Java 17, le mot-clé strictfp a été ajouté dans les classes et les méthodes où une sémantique stricte est requise. Ce mot-clé va permettre de contrôler le comportement de la virgule flottante une fois placé devant la déclaration de la classe, interface ou méthode…

●	strictfp class myClass {...}
●	strictfp interface myInterface{...}
●	strictfp type myMethod(){...}

Divers types de jeux d’instructions ont été également introduits dans les CPU pour permettre d’utiliser cette sémantique stricte. De ce fait, la sémantique par défaut précédente est supprimée et toutes les opérations à virgule flottante sont dorénavant exécutées strictement. Le terme strictfp reste toutefois présent. Cependant, il n’a aucun effet et son utilisation provoque un avertissement.

9. Prise en charge de macOS et AArch64

Java 17 intègre notamment l’amélioration de la prise en charge de macOS sur l’architecture AArch64 à l’aide de JEP 391. En comparaison, la prise en charge de la plate-forme Linux sur l’architecture AArch64 a été ajoutée dans Java 9 et celle de Windows/AArch64 dans Java 16.

Conclusion :

Le concept LTS :

Maintenir plusieurs applications ou serveurs à jour avec la dernière version de Java, peut s’avérer parfois compliqué, surtout quand 5 sont déjà sorties depuis fin 2019. C’est pourquoi le concept d’un LTS a été créé. Une version Java LTS (support à long terme) est une version de Java qui restera la norme de l’industrie pendant plusieurs années. Par exemple, Java 8 qui est sorti en 2014, continuera à recevoir des mises à jour jusqu’en 2020, et le support étendu prendra fin d’ici 2025. À l’heure actuelle, la seule autre version de Java qui est également une version LTS est Java 11, qui a été publiée en 2018. Ceci ne remet pas en question la stabilité des versions non-LTS car celles-ci affinent certaines ou toutes les fonctionnalités introduites dans la dernière version LTS sans affecter le langage dans son ensemble.

Migrer vers Java 17 ?

La migration vers Java 17 nécessite certainement des efforts pour tirer le meilleur parti des nouvelles fonctionnalités et améliorations de la JVM. Pour passer facilement à Java 17 avec un minimum d’effort et de temps, on peut utiliser Docker à cet effet. Les développeurs pourront ainsi définir leurs pipelines d’intégration/déploiement continu (CI/CD) et tout exécuter dans des images Docker qui s’exécutent avec jdk 17. Ceci permet de ne pas affecter les autres applications/équipes utilisant d’anciennes versions de Java.

Migrer vers Java X ou vers la dernière version LTS ?

Oui, il est toujours recommandé de mettre à niveau vers la version la plus récente, mais pas dès le premier jour. Le logiciel et les bibliothèques que vous utilisez n’ont peut-être pas été mis à jour pour inclure la compatibilité avec Java 17, il vaut mieux attendre un certain temps jusqu’à ce que cela soit fait. Comme il s’agit d’une version de maintenance à long terme, il y a de fortes chances que votre environnement de production soit éventuellement mis à jour vers Java 17.

Si vous commencez un tout nouveau projet, le choix de Java 17 est probablement le plus judicieux car il réduit les coûts de migration. Cela permet également aux développeurs de tirer avantage de toutes les dernières fonctionnalités, telles que la prise en charge améliorée des conteneurs s’exécutant sur Java, ainsi que de nouvelles implémentations de ramasse-miettes à faible latence.

Pour les versions non LTS, une migration est toujours envisageable. On recommande particulièrement la désactivation des fonctionnalités en preview surtout en production. Cela implique qu’il faut recompiler ces fonctionnalités sur la prochaine version, mais ça permet de donner un meilleur feedback pour l’équipe java en vue de peaufiner ces fonctionnalités introduites en préversion ou de les déprécier sur les futures releases.

Références

Devoxx 2021 : https://przybyl.org/pres/2021/Java17-Whats-new-and-noteworthy/DevoxxFR.html#/feedback

Oracle :

https://www.oracle.com/be-fr/news/announcement/oracle-announces-java-16-2021-03-16.html
https://blogs.oracle.com/java/post/announcing-java17
https://blogs.oracle.com/javamagazine/post/the-hidden-gems-in-java-16-and-java-17-from-streammapmulti-to-hexformat
https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/stream/Stream.html#mapMulti(java.util.function.BiConsumer)

Blogs :

https://www.infoq.com/fr/articles/java-16-new-features/
https://www.loicmathieu.fr/wordpress/informatique/java-17-quoi-de-neuf/
https://geekflare.com/fr/whats-new-in-java/