Java 13 est sorti en Septembre 2019, les nouveautés les plus visibles pour le développeur sont la possibilité d’écrire des ‘Text Blocks’ et l’introduction du mot clé ‘yield’ dans les expressions Switch.
Il y a aussi d’autres nouveautés; une nouvelle implémentation de l’API de socket héritée (legacy socket API), l’amélioration du ramasse-miettes ZGC et l’archivage dynamique des classes d’application à l’aide d’AppCDS dans HotSpot.
Découvrons ce qui se cache derrière ces notions, comment les utiliser!
Switch Expressions
L’expression Switch a été aussi modifiée en JAVA12, dans la JEP 325. Le Switch n’est plus juste une structure de contrôle comme les bloques if/else mais peut renvoyer une valeur tout en utilisant une nouvelle syntaxe plus pratique et plus concise qui utilise l’opérateur arrow (->) et sans le mot clé ‘break’.
Voici un programme qui utilise la syntaxe des Expressions Switch en JAVA 12 :
int numSeason = switch (Months) { case January, February, March -> 1; case April, May June -> 2 ; case July, August, September -> 3 ; case October, November, December -> 4 ; }
L’introduction du mot clé ‘yield’ est décrite dans la JEP-354. Son intérêt, pour reprendre les mots de l’auteur (Brian Goetz) est “…Ces modifications vont simplifier le codage quotidien et préparer la voie à l’utilisation du filtrage par motif dans switch ” (En anglais dans le texte : “… These changes will simplify everyday coding, and prepare the way for the use of pattern matching (JEP 305) in switch.”)
- La syntaxe
La modification s’agit d’ajouter un nouveau mot clé ‘yield’ pour retourner l’élément depuis une branche du switch. Auparavant on utilisait break « value » maintenant on doit utiliser yield « value ».
- Utilisation
Voici un exemple d’utilisation :
int numberSeason = switch (months) { case January: yield 1 ; case February: yield 2 ; case March: yield 3 ; case April: yield 4 ; case May: yield 5 ; case June: yield 6 ; case July: yield 7 ; case August: yield 8 ; case September: yield 9 ; case October: yield 10 ; case November: yield 11 ; case December: yield 12 ; default: throw new IllegalArgumentException("Unexpected value: " + months); };
Text Blocks
La grande nouveauté de la version 13 de Java, la possibilité d’écrire des Text Blocks : un nouveau type de String Literal qui permet de les écrire sur plusieurs lignes.
Cette nouveauté est décrite dans la JEP-355. Son intérêt, pour reprendre les mots de l’auteur (Brian Goetz) est ” Un bloc de texte est une chaîne de caractères à plusieurs lignes pour ne plus avoir besoin de la plupart des séquences d’échappement. Un bloc de texte formate automatiquement la chaîne de caractères d’une manière prévisible et donne aux développeurs le contrôle sur le format souhaité” (En anglais dans le texte : A text block is a multi-line string literal that avoids the need for most escape sequences, automatically formats the string in a predictable way, and gives the developer control over format when desired ”).
Avant JAVA 13, écrire un extrait de code HTML, XML, SQL ou JSON dans une chaîne littérale nécessite généralement une édition importante avec des échappements et des concaténations ce qui donne un fragment de code difficile à lire et à maintenir.
Un algorithme un peu complexe a été implémenté pour conserver les espaces et les retours à la ligne telle que le développeur avait l’intention de la définir.
Ci-dessous quelques exemples avant JAVA13.
Exemple de syntaxe en SQL :
String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" + "WHERE `CITY` = 'MARRAKECH'\n" + "ORDER BY `EMP_ID`, `LAST_NAME`;\n";
Exemple de syntaxe en html :
String html ="<html>\n" + " <body>\n" + " <p>Hello, World</p>\n" + " </body>\n" + "</html>\n";
Exemple de syntaxe en JSON :
String json ="{\n" + " \"name\":\"hanane\",\n" + " \"age\":27\n" + "}\n";
La syntaxe
Au lieu d’utiliser un seul caractère d’échappement ‘ \n’ il suffit d’utiliser une séquence : « » »
Les règles principales des Text Blocks sont:
- Commencer par « » » et un retour à la ligne.
- Suppression de l’indentation accidentelle et du premier retour à la ligne.
- Conservation du reste de l’indentation.
- Terminer par « » » sans retour à la ligne préalable.
- On peut utiliser une double-quote à l’intérieur d’un Text Block
- Utilisation
Exemple syntaxe en sql :
String query = """ SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB` WHERE `CITY` = 'MARRAKECH' ORDER BY `EMP_ID`, `LAST_NAME`; """;
Exemple syntaxe en html :
String html = """ <html> <body> <p>Hello, World</p> </body> </html> """;
Exemple syntaxe en JSON :
String json = """ { "name":"hanane", "age":27 } """;
Dans le cadre ce changement, trois nouvelles méthodes ont été ajoutées à la classe String.
- translateEscapes() – traduit les séquences d’échappement dans la chaîne except pour les séquences unicode.
- stripIndent() – supprime les espaces communs depuis le début de chaque ligne
- formatted(Object… args) – Méthode pratique, équivalente à la method String.format(string, args)
Nouvelle implémentation de l’API de socket héritée (legacy socket API)
L’API socket en Java a été introduite dans le JDK 1.0. L’interface Java des sockets offre un accès simple aux sockets sur IP en utilisant plusieurs classes qui interviennent lors de la réalisation d’une communication par sockets.
Depuis son implémentation, ce mélange de code Java et C hérité a nécessité une augmentation à plusieurs reprises de la taille de la pile de threads par défaut et a causé des problèmes de fiabilité et de concurrence au fil du temps. Nous arrivons maintenant à un point où la seule solution est une refonte complète.
L’implémentation de l’API (the Legacy Socket API) est décrite dans la JEP-353. Son intérêt, pour reprendre les mots de l’auteur (Brian Goetz) est “Remplacer l’implémentation actuelle qui utilise les APIs java.net.Socket and java.net.ServerSocket par une implémentation plus simple et moderne qui permet une maintenance et un débogage facile…” (En anglais dans le texte : Replace the underlying implementation used by the java.net.Socket and java.net.ServerSocket APIs with a simpler and more modern implementation that is easy to maintain and debug..”)
Voici quelques points sur la nouvelle implémentation:
- La nouvelle implémentation est compatible avec l’ancienne, les opérations de socket utilisant des délais d’expiration (connexion, acceptation, lecture) sont implémentées.
- Le mécanisme java.lang.ref.Cleaner est utilisé pour fermer les sockets lorsque le SocketImpl est récupéré par le GC ou bien lorsque le socket n’a pas été explicitement fermé.
- La réinitialisation de la connexion est implémentée de la même manière que l’ancienne implémentation afin que les tentatives de lecture après une réinitialisation de la connexion échouent de manière cohérente.
Voici quelques méthodes:
- accept() : accepte une connexion entrante
- void close() : ferme la socket
- InetAddress getInetAddress() : retourne l’adresse du serveur
- int getLocalPort() : retourne le port sur lequel le serveur écoute
Les améliorations apportées à ZGC (Z Garbage Collector)
ZGC est une nouvelle génération de GC (ramasse-miettes) est l’un des nouveautés de JAVA11. La JEP-333 a décrit le ZGC comme étant un ramasse-miettes évolutif et à faible latence, pouvant atteindre des performances très élevées avec des heap de très grandes tailles (10ms max de pause avec des heap pouvant aller jusqu’au To).
Des améliorations ont été apportées à ZGC dans la JEP-351. L’intérêt pour reprendre les mots de l’auteur (Brian Goetz) est ” ZGC ne renvoie pas actuellement le mémoire au système d’exploitation, même lorsque cette mémoire n’a pas été utilisée depuis longtemps. Ce comportement n’est pas optimal pour tous les types d’applications et d’environnements, en particulier ceux où l’empreinte mémoire est un problème” (En anglais dans le texte : ZGC does not currently uncommit and return memory to the operating system, even when that memory has been unused for a long time. This behavior is not optimal for all types of applications and environments, especially those where memory footprint is a concern”).
Avec l’introduction de JPED-351, le ZGC sera en mesure de libérer la mémoire afin qu’elle soit à nouveau disponible pour le système d’exploitation.
Le ZGC se compose d’un ensemble de régions de tas appelées ZPages, chacune contenant des quantités variables de mémoire. Lorsque les pages Z sont libérées, elles sont ajoutées à un cache de pages prêtes à être réutilisées. Ces pages mises en cache ne sont pas actuellement utilisées dans l’application et peuvent être renvoyé au système d’exploitation.
Dans cette version, le ZGC utiliserait une politique de délai d’expiration simple pour déterminer quand un ZPage n’est pas utilisé.
Ces améliorations ont plusieurs avantages évidents sur la performance d’une application, car l’allocation de mémoire soit limitée à ce dont nous avons réellement besoin.
Cela serait encore plus avantageux dans les environnements de conteneurs où les ressources sont limitées ou où des frais sont facturés en fonction des ressources utilisées.
Dans les environnements où une application peut devenir inactive et où d’autres continuent de fonctionner, le ZGC peut libérer plus de mémoire pour d’autres applications.
Il convient de noter que cette fonctionnalité existe déjà dans les GC G1 et Shenandoah, l’ajouter à ZGC la rend beaucoup plus efficace pour de nombreux utilisateurs.
L’archivage dynamique des classes
Cette nouveauté est décrite dans la JEP-350. Son intérêt, pour reprendre les mots de l’auteur (Brian Goetz) est ” Étendez le partage de données de classe d’application pour permettre l’archivage dynamique des classes à la fin de l’exécution de l’application Java. Les classes archivées incluront toutes les classes d’application et classes de bibliothèque chargées qui ne sont pas présentes dans l’archive CDS par défaut de la couche de base.
” (En anglais dans le texte : Extend application class-data sharing to allow the dynamic archiving of classes at the end of Java application execution. The archived classes will include all loaded application classes and library classes that are not present in the default, base-layer CDS archive.”).
L’archivage des classes d’application à l’aide d’AppCDS dans HotSpot offre des avantages supplémentaires en matière de temps de démarrage et de mémoire par rapport à l’archive CDS par défaut.
Cependant, actuellement une procédure en trois étapes est requise pour utiliser AppCDS pour une application Java:
- Faites un ou plusieurs essais pour créer une liste de classes
- Vider une archive à l’aide de la liste de classes créée
- Exécuter avec l’archive
L’archivage dynamique activé par une option de ligne de commande simplifiera l’utilisation d’AppCDS en éliminant les exécutions d’essai (étape 1 ci-dessus) et prendra en charge les chargeurs de classe intégrés et les chargeurs de classe définis par l’utilisateur de manière efficace et uniforme.
Une amélioration de suivi de ce JEP pourrait effectuer la génération d’archives automatique lors de la première exécution d’une application. Cela éliminerait l’étape de création explicite d’archive (étape 2 ci-dessus). L’utilisation de CDS / AppCDS pourrait alors être complètement transparente et automatique.
La grande nouveauté de la version 13 de Java, la possibilité d’écrire des Text Blocks : un nouveau type de String Literal qui permet de les écrire sur plusieurs lignes.
Il n’y a plus la galère d’écrire du texte dans une chaîne de caractère et devoir mettre toujours des « \ » pour les caractères spéciaux et mettre des « \n » pour le retour à la ligne ou le souci des espace, il suffit d’écrire les lignes des chaines de caractères entre « » « ».
L’autre nouveauté visible pour le développeur est l’introduction du mot clé ‘yield’ dans les expressions Switch pour retourner l’élément depuis une branche du switch.