{"id":217,"date":"2020-05-07T12:03:00","date_gmt":"2020-05-07T10:03:00","guid":{"rendered":"http:\/\/baptiste-meynier.com\/?p=217"},"modified":"2023-02-18T18:48:06","modified_gmt":"2023-02-18T17:48:06","slug":"graalvm","status":"publish","type":"post","link":"https:\/\/baptiste-meynier.com\/index.php\/2020\/05\/07\/graalvm\/","title":{"rendered":"GraalVM"},"content":{"rendered":"\n<p>Il y a 25 ans, la soci\u00e9t\u00e9 Sun cr\u00e9ait le langage Java. La jvm n\u2019a cess\u00e9 de gagner en performance et s\u2019enrichir en fonctionnalit\u00e9s. Une grande partie du succ\u00e8s du Java r\u00e9side sur sa portabilit\u00e9 et sa facilit\u00e9 de gestion de la m\u00e9moire avec son garbage collector. Cependant, nous oublions souvent de citer son syst\u00e8me de compilation \u00e0 chaud, le Just In Time.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Mais c\u2019est quoi la compilation \u00e0 chaud ?<\/h2>\n\n\n\n<p>Il s\u2019agit d\u2019une technique visant \u00e0 am\u00e9liorer la performance de bytecode-compil\u00e9s par une traduction en code machine natif au moment de l\u2019ex\u00e9cution. La compilation \u00e0 la vol\u00e9e se fonde sur deux anciennes id\u00e9es : la compilation de bytecode et la compilation dynamique.<\/p>\n\n\n\n<p>Dans un syst\u00e8me dit bytecode-compil\u00e9, le code source est compil\u00e9 \u00e0 l\u2019avance ou \u00e0 la vol\u00e9e (lors de l\u2019ex\u00e9cution) dans une repr\u00e9sentation interm\u00e9diaire, le bytecode. C\u2019est le cas par exemple des langages Limbo, Smalltalk, Perl, PHP, Python, Ruby, Lua, GNU Common Lisp ou encore Java, entre autres.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER GraalArticle]$ vi Greeting.java\n[baptiste@BMEYNIER GraalArticle]$ javac Greeting.java \n[baptiste@BMEYNIER GraalArticle]$ ls -als\ntotal 16\n4 drwxr-xr-x. 2 baptiste baptiste 4096 14 mai   10:54 .\n4 drwxr-xr-x. 3 baptiste baptiste 4096 14 mai   10:50 ..\n4 -rw-rw-r--. 1 baptiste baptiste  461 14 mai   10:54 Greeting.class &lt;= ByteCode\n4 -rw-rw-r--. 1 baptiste baptiste  125 14 mai   10:53 Greeting.java\n[baptiste@BMEYNIER GraalArticle]$ java Greeting \nHello !<\/code><\/pre>\n\n\n\n<p>Le bytecode n\u2019est pas un code machine, c\u2019est-\u00e0-dire que ce n\u2019est pas un code optimis\u00e9 pour un type d\u2019architecture d\u2019ordinateur en particulier. On dit du bytecode qu\u2019il est portable entre diff\u00e9rentes architectures. Ce bytecode est ensuite interpr\u00e9t\u00e9 ou bien ex\u00e9cut\u00e9 par une machine virtuelle.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"364\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/compilation_circle.png\" alt=\"\" class=\"wp-image-225\" srcset=\"https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/compilation_circle.png 1024w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/compilation_circle-300x107.png 300w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/compilation_circle-768x273.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>La production de bytecode n\u2019est que la premi\u00e8re \u00e9tape d\u2019un processus d\u2019ex\u00e9cution plus complexe. Le bytecode est ensuite d\u00e9ploy\u00e9 sur le syst\u00e8me cible, lors de son execution le JIT, le traduit en code machine natif (ie. optimis\u00e9 pour l\u2019architecture de la machine ex\u00e9cutant le programme). Ceci peut \u00eatre fait sur un fichier entier, ou sp\u00e9cifiquement sur une fonction du programme.<\/p>\n\n\n\n<p>La compilation \u00e0 la vol\u00e9e s\u2019adapte dynamiquement \u00e0 la charge de travail courante du logiciel, en compilant le code \u00ab chaud \u00bb, c\u2019est-\u00e0-dire le code le plus utilis\u00e9 \u00e0 un moment donn\u00e9. Obtenir du code machine optimis\u00e9 se fait beaucoup plus rapidement depuis du bytecode que depuis du code source. Comme le bytecode d\u00e9ploy\u00e9 est portable, la compilation \u00e0 la vol\u00e9e est envisageable pour tout type d\u2019architecture, \u00e0 la condition d\u2019avoir un compilateur JIT pour cette architecture.<\/p>\n\n\n\n<h6 class=\"wp-block-heading\">LES SOURCES DE L\u2019OPENJDK SONT CONSULTABLES SUR&nbsp;<a href=\"https:\/\/github.com\/openjdk\/jdk11u-dev\" target=\"_blank\" rel=\"noreferrer noopener\">GITHUB<\/a>.<\/h6>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"995\" height=\"363\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/openjdk11_languages.png\" alt=\"\" class=\"wp-image-226\" srcset=\"https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/openjdk11_languages.png 995w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/openjdk11_languages-300x109.png 300w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/openjdk11_languages-768x280.png 768w\" sizes=\"auto, (max-width: 995px) 100vw, 995px\" \/><\/figure>\n<\/div>\n\n\n<p>Vous remarquerez qu\u2019il est compos\u00e9 de sources de plusieurs langages.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">EN PARCOURANT LES SOURCES, NOUS TROUVONS DU CODE C++ SP\u00c9CIFIQUE \u00c0 DE NOMBREUSES ARCHITECTURES :<\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER hotspot]$ tree . -d\n.\n\u251c\u2500\u2500 cpu\n\u2502   \u251c\u2500\u2500 aarch64\n\u2502   \u251c\u2500\u2500 arm\n\u2502   \u251c\u2500\u2500 ppc\n\u2502   \u251c\u2500\u2500 s390\n\u2502   \u251c\u2500\u2500 sparc\n\u2502   \u251c\u2500\u2500 x86\n\u2502   \u2514\u2500\u2500 zero\n\u251c\u2500\u2500 os\n\u2502   \u251c\u2500\u2500 aix\n\u2502   \u251c\u2500\u2500 bsd\n\u2502   \u251c\u2500\u2500 linux\n\u2502   \u251c\u2500\u2500 posix\n\u2502   \u251c\u2500\u2500 solaris\n\u2502   \u2514\u2500\u2500 windows\n\u2514\u2500\u2500 os_cpu\n    \u251c\u2500\u2500 aix_ppc\n    \u251c\u2500\u2500 bsd_x86\n    \u251c\u2500\u2500 bsd_zero\n    \u251c\u2500\u2500 linux_aarch64\n    \u251c\u2500\u2500 linux_arm\n    \u251c\u2500\u2500 linux_ppc\n    \u251c\u2500\u2500 linux_s390\n    \u251c\u2500\u2500 linux_sparc\n    \u251c\u2500\u2500 linux_x86\n    \u251c\u2500\u2500 linux_zero\n    \u251c\u2500\u2500 solaris_sparc\n    \u251c\u2500\u2500 solaris_x86\n    \u2514\u2500\u2500 windows_x86<\/code><\/pre>\n\n\n\n<p>Le JIT est compos\u00e9 de deux compilateurs :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>C1 est le compilateur le plus rapide \u00e0 produire du code natif. Il est aussi appel\u00e9 Client parce qu\u2019il minimise la latence et sera plus adapt\u00e9 au application de cycle vie court.<\/li>\n\n\n\n<li>C2 est plus lent \u00e0 transformer le bytecode mais produit du code natif plus optimis\u00e9 que C1. Il est aussi appel\u00e9 Server car plus adapt\u00e9 aux applications au cycle de vie long tel que les serveurs.<\/li>\n<\/ul>\n\n\n\n<div style=\"height:51px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h5 class=\"wp-block-heading\">LA JVM COMBINE L\u2019USAGE DE CES DEUX COMPILATEURS.<\/h5>\n\n\n\n<p>Lors de la premi\u00e8re ex\u00e9cution du code, la Jvm utilisera le C1. La compilation C2 se d\u00e9clenche selon une table de statistiques maintenue par la Jvm, c\u2019est elle qui d\u00e9cidera de son lancement.<\/p>\n\n\n\n<p>L\u2019usage de ce m\u00e9canisme a permis de faire des gains \u00e9normes en performance, mais C2 est devenu de plus en plus complexe et difficile \u00e0 maintenir. C\u2019est en ayant conscience des limitations de cette technique que la soci\u00e9t\u00e9 Oracle publia dans sa version 9 de Java une API permettant de fournir sa propre impl\u00e9mentation de compilation de code (<a href=\"http:\/\/openjdk.java.net\/jeps\/243\">JEP-243<\/a>). C\u2019est l\u00e0 qu\u2019intervient GraalVM !<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"510\" height=\"102\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/graalvm_logo.png\" alt=\"\" class=\"wp-image-242\" srcset=\"https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/graalvm_logo.png 510w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/graalvm_logo-300x60.png 300w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/figure>\n<\/div>\n\n\n<p><br>GraalVM est une machine virtuelle d\u00e9velopp\u00e9e par Oracle. Bien que bas\u00e9e sur la HotSpot nous allons voir en quoi cette JVM en est diff\u00e9rente.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Mise en place :<\/h4>\n\n\n\n<p>GraalVm est divis\u00e9e en deux \u00e9ditions la Community et l\u2019Entreprise Edition. Pour un usage personnel il est tout \u00e0 fait possible de&nbsp;<a href=\"https:\/\/www.oracle.com\/downloads\/graalvm-downloads.html\">t\u00e9l\u00e9charger la version Entreprise<\/a>. Deux versions de HotSpot sont propos\u00e9es la 8 et la 11.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER latest]$ $GRAALVM_HOME\/bin\/java -version\njava version \"11.0.7\" 2020-04-14 LTS\nJava(TM) SE Runtime Environment GraalVM EE 20.0.1 (build 11.0.7+8-LTS-jvmci-20.0-b04)\nJava HotSpot(TM) 64-Bit Server VM GraalVM EE 20.0.1 (build 11.0.7+8-LTS-jvmci-20.0-b04, mixed mode, sharing)<\/code><\/pre>\n\n\n\n<div style=\"height:51px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">UNE NOUVELLE IMPL\u00c9MENTATION DU JIT<\/h3>\n\n\n\n<p>Son impl\u00e9mentation a totalement \u00e9t\u00e9 revue, le C++ a \u00e9t\u00e9 remplac\u00e9 par du Java, plus facile \u00e0 maintenir.<\/p>\n\n\n\n<p>Pour le tester nous suivrons un exemple propos\u00e9 sur le site de&nbsp;<a href=\"https:\/\/www.graalvm.org\/\">GraalVM<\/a>&nbsp;(n\u2019h\u00e9sitez pas \u00e0 y faire un tour).<\/p>\n\n\n\n<p>Voici un programme permettant de compter le nombre de caract\u00e8res en majuscule dans un texte, ex\u00e9cut\u00e9 de nombreuses fois.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">public class CountUppercase {\n    static final int ITERATIONS = Math.max(Integer.getInteger(\"iterations\", 1), 1);\n    public static void main(String[] args) {\n        String sentence = String.join(\" \", args);\n        for (int iter = 0; iter &lt; ITERATIONS; iter++) {\n            if (ITERATIONS != 1) System.out.println(\"-- iteration \" + (iter + 1) + \" --\");\n            long total = 0, start = System.currentTimeMillis(), last = start;\n            for (int i = 1; i &lt; 10_000_000; i++) {\n                total += sentence.chars().filter(Character::isUpperCase).count();\n                if (i % 1_000_000 == 0) {\n                    long now = System.currentTimeMillis();\n                    System.out.printf(\"%d (%d ms)%n\", i \/ 1_000_000, now - last);\n                    last = now;\n                }\n            }\n            System.out.printf(\"total: %d (%d ms)%n\", total, System.currentTimeMillis() - start);\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<p>Nous allons ex\u00e9cuter ce code en d\u00e9sactivant la nouvelle version du JIT avec l\u2019argument&nbsp;<code>-XX:-UseJVMCICompiler<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER tuto_graalvm]$ $GRAALVM_HOME\/bin\/javac CountUppercase.java\n[baptiste@BMEYNIER tuto_graalvm]$ $GRAALVM_HOME\/bin\/java -XX:-UseJVMCICompiler CountUppercase In 2020 I would like to run ALL languages in one VM.\n1 (497 ms)\n2 (433 ms)\n3 (415 ms)\n4 (410 ms)\n5 (415 ms)\n6 (414 ms)\n7 (415 ms)\n8 (414 ms)\n9 (413 ms)\ntotal: 69999993 (4239 ms)<\/code><\/pre>\n\n\n\n<p>Le traitement a pris 4239 ms.<\/p>\n\n\n\n<p>En apart\u00e9, le \u2013 d\u00e9sactive (<code>-XX:<strong>-<\/strong>UseJVMCICompiler<\/code>) et le + active (<code>-XX:<strong>+<\/strong>UseJVMCICompiler<\/code>).<\/p>\n\n\n\n<p>Nous allons relancer la m\u00eame ex\u00e9cution en laissant le JVMCICompiler activ\u00e9 par d\u00e9faut.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER tuto_graalvm]$ $GRAALVM_HOME\/bin\/java CountUppercase In 2020 I would like to run ALL languages in one VM.\n1 (152 ms)\n2 (152 ms)\n3 (79 ms)\n4 (77 ms)\n5 (79 ms)\n6 (78 ms)\n7 (77 ms)\n8 (80 ms)\n9 (79 ms)\ntotal: 69999993 (932 ms)<\/code><\/pre>\n\n\n\n<p>Cette fois-ci l\u2019ex\u00e9cution a pris 920 ms, soit 4 fois moins de temps !<\/p>\n\n\n\n<div style=\"height:53px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">LA COMPILATION NATIVE<\/h3>\n\n\n\n<p>Aussi appel\u00e9 AOT (Ahead Of Time), cette fonctionnalit\u00e9 a \u00e9t\u00e9 introduite dans Java 9 via la&nbsp;<a href=\"https:\/\/openjdk.java.net\/jeps\/295\">JEP 295<\/a>. L\u2019id\u00e9e est de consid\u00e9rer que tout ce qui est fait par le JIT en runtime peut \u00eatre r\u00e9alis\u00e9 en phase de compilation.<\/p>\n\n\n\n<p>Prenons une classe dont une fonction est appel\u00e9e plusieurs fois d\u2019affil\u00e9 :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">public class MultipleCall {\n\n  public int f() throws Exception {\n    int a = 5;\n    return a;\n  }\n\n  public static void main(String[] args) throws Exception {\n    for (int i = 1; i &lt;= 10; i++) {\n      System.out.println(\"call \" + Integer.valueOf(i));\n      long a = System.nanoTime();\n      new Test().f();\n      long b = System.nanoTime();\n      System.out.println(\"elapsed= \" + (b-a));\n    }\n\n  }\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Commen\u00e7ons par exp\u00e9rimenter ce programme via une HotSpot :<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER tuto_graalvm]$ $JAVA_HOME\/bin\/java -version\nopenjdk version \"11.0.5\" 2019-10-15\nOpenJDK Runtime Environment AdoptOpenJDK (build 11.0.5+10)\nOpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.5+10, mixed mode)\n[baptiste@BMEYNIER native-list-dir]$ $JAVA_HOME\/bin\/javac MultipleCall.java \n[baptiste@BMEYNIER native-list-dir]$ time $JAVA_HOME\/bin\/java MultipleCall \n[baptiste@BMEYNIER 02_AOT_HOTSPOT]$ $JAVA_HOME\/bin\/java Test\ncall 1\nelapsed= 3740\ncall 2\nelapsed= 709\ncall 3\nelapsed= 352\ncall 4\nelapsed= 317\ncall 5\nelapsed= 349\ncall 6\nelapsed= 306\ncall 7\nelapsed= 281\ncall 8\nelapsed= 297\ncall 9\nelapsed= 295\ncall 10\nelapsed= 322<\/code><\/pre>\n\n\n\n<p>Pour utiliser l\u2019AOT il nous faut utiliser l\u2019ex\u00e9cutable jaotc<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER native-list-dir]$ $JAVA_HOME\/bin\/jaotc --output MultipleCall.so MultipleCall<\/code><\/pre>\n\n\n\n<p>Cette commande va convertir notre fichier Java en une librairie dans un format appel\u00e9 SharedObjects (.so).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER tuto_graalvm]$ ls -alhs\ntotal 8,1M\n4,0K drwxr-xr-x.  3 baptiste baptiste 4,0K 14 mai   17:58  .\n4,0K drwxr-xr-x.  9 baptiste baptiste 4,0K 14 mai   10:49  ..\n4,0K -rw-rw-r--.  1 baptiste baptiste 2,4K 14 mai   17:57  MultipleCall.class\n4,0K -rw-rw-r--.  1 baptiste baptiste  929  2 mai   11:44  MultipleCall.java\n144K -rw-rw-r--.  1 baptiste baptiste 141K 14 mai   17:58  MultipleCall.so<\/code><\/pre>\n\n\n\n<p>Nous l\u2019executerons de la mani\u00e8re suivante:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER tuto_graalvm]$ $JAVA_HOME\/bin\/java -XX:AOTLibrary=.\/MultipleCall.so MultipleCall \ncall 1\nelapsed= 2227\ncall 2\nelapsed= 945\ncall 3\nelapsed= 368\ncall 4\nelapsed= 287\ncall 5\nelapsed= 296\ncall 6\nelapsed= 227\ncall 7\nelapsed= 263\ncall 8\nelapsed= 263\ncall 9\nelapsed= 296\ncall 10\nelapsed= 298<\/code><\/pre>\n\n\n\n<p>On constate de meilleurs performances au d\u00e9marrage, les r\u00e9sultats finissent ensuite par tendre vers les m\u00eames r\u00e9sultats. Il est faux de se dire que l\u2019AOT permet d\u2019avoir un programme bien plus performant, en revanche il permet d\u2019acc\u00e9der plus rapidement \u00e0 un code optimal, l\u00e0 ou le JIT aurait n\u00e9cessit\u00e9 plusieurs it\u00e9rations.&nbsp; A noter qu\u2019il est \u00e9galement possible d\u2019effectuer cette manipulation sur un module notamment ceux du JDK.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"364\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/graalvm_compilation_circle.png\" alt=\"\" class=\"wp-image-228\" srcset=\"https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/graalvm_compilation_circle.png 1024w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/graalvm_compilation_circle-300x107.png 300w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/graalvm_compilation_circle-768x273.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n<div style=\"height:59px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Exp\u00e9rimentons cette fonctionnalit\u00e9 avec GraalVM<\/h2>\n\n\n\n<p>Prenons le code suivant trouv\u00e9 sur le site officiel de GraalVM:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">import java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.stream.Stream;\n\npublic class ListDir {\n        public static void main(String[] args) throws java.io.IOException {\n\n                String root = \".\";\n                if(args.length &gt; 0) {\n                        root = args[0];\n                }\n                System.out.println(\"Walking path: \" + Paths.get(root));\n\n                long[] size = {0};\n                long[] count = {0};\n\n                try (Stream&lt;Path&gt; paths = Files.walk(Paths.get(root))) {\n                        paths.filter(Files::isRegularFile).forEach((Path p) -&gt; {\n                                File f = p.toFile();\n                                size[0] += f.length();\n                                count[0] += 1;\n                        });\n                }\n\n                System.out.println(\"Total: \" + count[0] + \" files, total size = \" + size[0] + \" bytes\");\n        }\n}<\/code><\/pre>\n\n\n\n<p>Voici le r\u00e9sultat d\u2019une \u00e9xecution classique:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER native-list-dir]$ $GRAALVM_HOME\/bin\/javac ListDir.java\n[baptiste@BMEYNIER native-list-dir]$ time $GRAALVM_HOME\/bin\/java ListDir ..\nWalking path: ..\nTotal: 611 files, total size = 55309806 bytes\n\nreal 0m0,197s\nuser 0m0,242s\nsys 0m0,041s<\/code><\/pre>\n\n\n\n<p>L\u2019ex\u00e9cutable de compilation native n\u2019est pas pr\u00e9sent par d\u00e9faut. Pour l\u2019\u00e9dition entreprise il va falloir le&nbsp;<a href=\"https:\/\/www.oracle.com\/downloads\/graalvm-downloads.html\">t\u00e9l\u00e9charger<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER ~]$ cd $GRAALVM_HOME\/bin\n[baptiste@BMEYNIER bin]$ .\/gu -L install native-image-installable-svm-svmee-java11-linux-amd64-20.0.1.jar \nProcessing Component archive: native-image-installable-svm-svmee-java11-linux-amd64-20.0.1.jar\nInstalling new component: Native Image (org.graalvm.native-image, version 20.0.1)\n[baptiste@BMEYNIER bin]$ ls -alhs\n0 lrwxrwxrwx.  1 baptiste baptiste        27 14 mai   19:09 native-image -&gt; ..\/lib\/svm\/bin\/native-image<\/code><\/pre>\n\n\n\n<p>L\u2019ex\u00e9cutable gu ou Graal Updater vous permet d\u2019installer des composants en ligne de commande.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER native-list-dir]$ $GRAALVM_HOME\/bin\/javac ListDir.java\n[baptiste@BMEYNIER native-list-dir]$ $GRAALVM_HOME\/bin\/native-image ListDir\nBuild on Server(pid: 20294, port: 43927)\n[listdir:20294]    classlist:     119.83 ms,  1.00 GB\n[listdir:20294]        (cap):     743.81 ms,  1.00 GB\n[listdir:20294]        setup:   1,945.27 ms,  1.00 GB\n[listdir:20294]   (typeflow):   5,436.31 ms,  1.20 GB\n[listdir:20294]    (objects):   3,881.34 ms,  1.20 GB\n[listdir:20294]   (features):     227.98 ms,  1.20 GB\n[listdir:20294]     analysis:   9,894.44 ms,  1.20 GB\n[listdir:20294]     (clinit):     189.02 ms,  1.20 GB\n[listdir:20294]     universe:     490.97 ms,  1.20 GB\n[listdir:20294]      (parse):   1,228.73 ms,  1.20 GB\n[listdir:20294]     (inline):   1,114.86 ms,  1.20 GB\n[listdir:20294]    (compile):   8,336.15 ms,  1.50 GB\n[listdir:20294]      compile:  11,062.47 ms,  1.50 GB\n[listdir:20294]        image:     686.83 ms,  1.50 GB\n[listdir:20294]        write:     137.18 ms,  1.50 GB\n[listdir:20294]      [total]:  24,546.82 ms,  1.50 GB<\/code><\/pre>\n\n\n\n<p>La premi\u00e8re chose que l\u2019on constate est que le temps de cr\u00e9ation de l\u2019image est tr\u00e8s long ! 25 secondes pour compiler une classe.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Mais que fait GraalVM pendant tout ce temps ?<\/h4>\n\n\n\n<p>GraalVM va effectuer tout un tas d\u2019optimisations, notamment \u00e9tablir un graph du code appel\u00e9, pour ensuite enlever le code inutile.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER native-list-dir]$ ls -alsh\ntotal 6,8M\n4,0K drwxrwxr-x.  2 baptiste baptiste 4,0K 15 mai   10:46 .\n4,0K drwxrwxr-x. 16 baptiste baptiste 4,0K  2 mai   12:15 ..\n6,7M -rwxrwxr-x.  1 baptiste baptiste 6,7M 15 mai   10:46 listdir<\/code><\/pre>\n\n\n\n<p>On constate que l\u2019ex\u00e9cutable p\u00e8se seulement 7M ! Pour le lancer, inutile de poss\u00e9der un JRE puisqu\u2019il s\u2019agit de code natif.<\/p>\n\n\n\n<h6 class=\"wp-block-heading\">IMAGINEZ LE GAIN POUR UNE IMAGE DOCKER !!!<\/h6>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER native-list-dir]$ time .\/listdir ..\nWalking path: ..\nTotal: 611 files, total size = 55309806 bytes\n\nreal 0m0,034s\nuser 0m0,014s\nsys 0m0,020s<\/code><\/pre>\n\n\n\n<p>On constate un gain suppl\u00e9mentaire par rapport \u00e0 l\u2019AOT de la HotSpot. A noter que les applications natives s\u2019ex\u00e9cutent sur machine virtuelle appel\u00e9e SubstrateVM.<\/p>\n\n\n\n<p>Ce n\u2019est pas termin\u00e9, Graal propose une fonctionnalit\u00e9 (dans sa version entreprise), permettant de cr\u00e9er un fichier de profiling lors de l\u2019ex\u00e9cution. Ce fichier peut \u00eatre utilis\u00e9 pour g\u00e9n\u00e9rer une image encore plus performante.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER native-list-dir]$ $GRAALVMEE_HOME\/bin\/native-image --pgo-instrument ListDir\n...\n[baptiste@BMEYNIER native-list-dir]$ time .\/listdir ..\nWalking path: ..\nTotal: 611 files, total size = 55309806 bytes\n\nreal 0m0,034s\nuser 0m0,014s\nsys 0m0,020s\n\n[baptiste@BMEYNIER native-list-dir]$ ls -als\ntotal 46188\n    4 drwxrwxr-x.  2 baptiste baptiste     4096 15 mai   11:19 .\n    4 drwxrwxr-x. 16 baptiste baptiste     4096  2 mai   12:15 ..\n 1840 -rw-------.  1 baptiste baptiste  1880350 15 mai   11:19 default.iprof\n \n[baptiste@BMEYNIER native-list-dir]$ $GRAALVMEE_HOME\/bin\/native-image --pgo ListDir\n[baptiste@BMEYNIER native-list-dir]$ time .\/listdir ..\nWalking path: ..\nTotal: 611 files, total size = 55309806 bytes\n\nreal 0m0,018s\nuser 0m0,006s\nsys 0m0,011s<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table is-style-regular\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-center\" data-align=\"center\">HotSpot 11<\/th><th class=\"has-text-align-center\" data-align=\"center\">GraalVM EE<\/th><th class=\"has-text-align-center\" data-align=\"center\">GraalVM EE Native Image<\/th><th class=\"has-text-align-center\" data-align=\"center\">GraalVM EE Native Image + pgo<\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-center\" data-align=\"center\">real 0m0,197s<\/td><td class=\"has-text-align-center\" data-align=\"center\">real 0m0,161s<\/td><td class=\"has-text-align-center\" data-align=\"center\">real 0m0,034s<\/td><td class=\"has-text-align-center\" data-align=\"center\">real 0m0,018s<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">user 0m0,242s<\/td><td class=\"has-text-align-center\" data-align=\"center\">user 0m0,277s<\/td><td class=\"has-text-align-center\" data-align=\"center\">user 0m0,014s<\/td><td class=\"has-text-align-center\" data-align=\"center\">user 0m0,006s<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">sys 0m0,041s<\/td><td class=\"has-text-align-center\" data-align=\"center\">sys 0m0,037s<\/td><td class=\"has-text-align-center\" data-align=\"center\">sys 0m0,020s<\/td><td class=\"has-text-align-center\" data-align=\"center\">sys 0m0,011s<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>R\u00e9sultat des courses, la taille de l\u2019ex\u00e9cutable p\u00e8se seulement 7 Mo, plut\u00f4t que 200 Mo de JRE + 5 Mo de Jar. Les performances sont bien meilleures, plus de 10 fois plus rapide. Parfait pour un contexte cloud !<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">MAIS TOUT \u00c7A N\u2019EST-T-IL PAS TROP BEAU ?<\/h3>\n\n\n\n<p>Eh oui, je ne vous ai pas tout dit. Ces avantages ont un prix, certaines fonctionnalit\u00e9s Java ne sont&nbsp;<a href=\"https:\/\/github.com\/oracle\/graal\/blob\/master\/substratevm\/LIMITATIONS.md\">pas disponibles<\/a>&nbsp;pour les images natives ! Je vous ai expliqu\u00e9 plus haut que lors de la cr\u00e9ation de l\u2019image, Graal effectuait un graph permettant de retirer le code inutile et cela lors de la phase de compilation.<\/p>\n\n\n\n<h6 class=\"wp-block-heading\">MAIS QU\u2019EN EST-IL DES INSTRUCTIONS EX\u00c9CUT\u00c9ES EN RUNTIME TELLES QUE LA R\u00c9FLEXION ? COMMENT LES INITIALISATIONS STATIQUES SONT-ELLES R\u00c9ALIS\u00c9ES ?<\/h6>\n\n\n\n<h4 class=\"wp-block-heading\">Commen\u00e7ons par nous int\u00e9resser \u00e0 la r\u00e9flexion<\/h4>\n\n\n\n<h5 class=\"wp-block-heading\">LA CONFIGURATION PAR FICHIER<\/h5>\n\n\n\n<p>Il suffit de lister les \u00e9l\u00e9ments pouvant \u00eatre la cible de r\u00e9flexion via un argument au moment de la g\u00e9n\u00e9ration de l\u2019image.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$GRAALVM_HOME\/bin\/native-image -H:ReflectionConfigurationFiles=\/path\/to\/reflectconfig -jar build\/libs\/aot-reflection-test.jar <\/code><\/pre>\n\n\n\n<p>Voici \u00e0 quoi ressemble le fichier, la d\u00e9claration peut \u00eatre fine et aller jusqu\u2019au niveau d\u2019un attribut ou m\u00e9thode d\u2019une classe.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">[\n  {\n    \"name\" : \"java.lang.Class\",\n    \"allDeclaredConstructors\" : true,\n    \"allPublicConstructors\" : true,\n    \"allDeclaredMethods\" : true,\n    \"allPublicMethods\" : true,\n    \"allDeclaredClasses\" : true,\n    \"allPublicClasses\" : true\n  },\n  {\n    \"name\" : \"java.lang.String\",\n    \"fields\" : [\n      { \"name\" : \"value\", \"allowWrite\" : true },\n      { \"name\" : \"hash\" }\n    ],\n    \"methods\" : [\n      { \"name\" : \"&lt;init&gt;\", \"parameterTypes\" : [] },\n      { \"name\" : \"&lt;init&gt;\", \"parameterTypes\" : [\"char[]\"] },\n      { \"name\" : \"charAt\" },\n      { \"name\" : \"format\", \"parameterTypes\" : [\"java.lang.String\", \"java.lang.Object[]\"] }\n    ]\n  },\n  {\n    \"name\" : \"java.lang.String$CaseInsensitiveComparator\",\n    \"methods\" : [\n      { \"name\" : \"compare\" }\n    ]\n  }\n]<\/code><\/pre>\n\n\n\n<p>Je vous joins les sources d\u2019un projet exp\u00e9rimentant certains comportements de r\u00e9flexion avec Graal.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">UTILISER LES FEATURES GRAAL :<\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">@AutomaticFeature\nclass RuntimeReflectionRegistrationFeature implements Feature {\n  public void beforeAnalysis(BeforeAnalysisAccess access) {\n    try {\n      RuntimeReflection.register(String.class);\n      RuntimeReflection.register(\/* finalIsWritable: *\/ true, String.class.getDeclaredField(\"value\"));\n      RuntimeReflection.register(String.class.getDeclaredField(\"hash\"));\n      RuntimeReflection.register(String.class.getDeclaredConstructor(char[].class));\n      RuntimeReflection.register(String.class.getDeclaredMethod(\"charAt\", int.class));\n      RuntimeReflection.register(String.class.getDeclaredMethod(\"format\", String.class, Object[].class));\n      RuntimeReflection.register(String.CaseInsensitiveComparator.class);\n      RuntimeReflection.register(String.CaseInsensitiveComparator.class.getDeclaredMethod(\"compare\", String.class, String.class));\n    } catch (NoSuchMethodException | NoSuchFieldException e) { ... }\n  }\n}<\/code><\/pre>\n\n\n\n<p>Graal propose une API Feature permettant de configurer programmatiquement son image en buildTime.<\/p>\n\n\n\n<h6 class=\"wp-block-heading\">SOLUTION 1:<\/h6>\n\n\n\n<p>Utiliser l\u2019annotation @AutomaticFeature<\/p>\n\n\n\n<h6 class=\"wp-block-heading\">SOLUTION 2:<\/h6>\n\n\n\n<p>L\u2019activer via un argument lors de la g\u00e9n\u00e9ration de l\u2019image : \u2013features=&lt;fqcn&gt;<\/p>\n\n\n\n<h6 class=\"wp-block-heading\">SOLUTION 3:<\/h6>\n\n\n\n<p>L\u2019activer via un fichier de configuration dans le r\u00e9pertoire Resources\/META-INF\/GROUP_ID\/ARTIFACT_ID\/native-image.properties<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">Args = --features=com.bmeynier.graalvm.reflection.ConfigureAtBuildTimeFeature<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Les initialisations de code static :<\/h4>\n\n\n\n<p>Par d\u00e9faut elle sont dor\u00e9navant r\u00e9alis\u00e9es en phase de runtime. Pour gagner en temps de lancement il est possible d\u2019effectuer ces initialisations lors de la g\u00e9n\u00e9ration de l\u2019image.<\/p>\n\n\n\n<p>Il vous faudra jouer avec ces deux arguments pour distinguer les classes a initialiser en :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>--initialize-at-build-time=&lt;liste des classes ou des packages s\u00e9par\u00e9es par une virgule&gt;<\/code><\/li>\n\n\n\n<li><code>--initialize-at-run-time=&lt;liste des classes ou des packages s\u00e9par\u00e9es par une virgule&gt;<\/code><\/li>\n<\/ul>\n\n\n\n<p>Pour les applications complexes, cette op\u00e9ration peut se r\u00e9v\u00e9ler \u00eatre un v\u00e9ritable casse-t\u00eate.<\/p>\n\n\n\n<p>Vous aurez alors la possibilit\u00e9 de tracer les d\u00e9pendances via l\u2019argument : -H:+TraceClassInitialization<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Et ce n\u2019est pas tout !<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[baptiste@BMEYNIER bin]$ ls\nbundle       javac      jhsdb       js            node            rmic\nbundler      javadoc    jimage      jshell        npm             rmid\ngem          javap      jinfo       jstack        pack200         rmiregistry\ngraalpython  jcmd       jjs         jstat         polyglot        Rscript\ngu           jconsole   jlink       jstatd        R               ruby\nirb          jdb        jmap        jvisualvm     rake            serialver\njar          jdeprscan  jmod        keytool       rdoc            truffleruby\njarsigner    jdeps      jps         lli           rebuild-images  unpack200\njava         jfr        jrunscript  native-image  ri<\/code><\/pre>\n\n\n\n<p>Et oui vous ne r\u00eavez pas, c\u2019est bien l\u2019ex\u00e9cutable Node que vous voyez. Je ne m\u2019\u00e9tendrai pas sur le sujet mais Graal est aussi une JVM dite polyglote. Elle est capable d\u2019ex\u00e9cuter du code de plusieurs langages ! Oracle fournit une API appel\u00e9e Truffle permettant \u00e0 un langage d\u2019exploiter le syst\u00e8me de gestion de la m\u00e9moire de sa machine virtuelle.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/archi_graalvm.png\" alt=\"\" class=\"wp-image-229\" width=\"848\" height=\"427\" srcset=\"https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/archi_graalvm.png 1024w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/archi_graalvm-300x151.png 300w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/archi_graalvm-768x387.png 768w\" sizes=\"auto, (max-width: 848px) 100vw, 848px\" \/><\/figure>\n<\/div>\n\n\n<div style=\"height:39px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Les outils<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\">Est-il possible de faire du remote d\u00e9bug d\u2019une application native ?<\/h4>\n\n\n\n<p>Pour les applications node JS oui, via devTool de Chrome.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ node --inspect --jvm HelloWorld.js\nDebugger listening on port 9229.\nTo start debugging, open the following URL in Chrome:\n    chrome-devtools:\/\/devtools\/bundled\/js_app.html?ws=127.0.1.1:9229\/76fcb6dd-35267eb09c3\nServer running at http:\/\/localhost:8000\/<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Peut-on utiliser VisualVM avec une application native ?<\/h4>\n\n\n\n<p>Oui pour la version Entreprise, en ajoutant l\u2019argument -H:+AllowVMInspection lors de la g\u00e9n\u00e9ration de l\u2019image. Attention vous n\u2019aurez pas acc\u00e8s aux Threads ou aux Beans JMX.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Existe-t-il un plugin maven ?<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"xml\" class=\"language-xml\">&lt;plugin&gt;\n    &lt;groupId&gt;com.oracle.substratevm&lt;\/groupId&gt;\n    &lt;artifactId&gt;native-image-maven-plugin&lt;\/artifactId&gt;\n    &lt;version&gt;${graalvm.plugin.version}&lt;\/version&gt;\n    &lt;executions&gt;\n        &lt;execution&gt;\n            &lt;goals&gt;\n                &lt;goal&gt;native-image&lt;\/goal&gt;\n            &lt;\/goals&gt;\n            &lt;phase&gt;package&lt;\/phase&gt;\n        &lt;\/execution&gt;\n    &lt;\/executions&gt;\n&lt;\/plugin&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Quels sont les frameworks Java compatibles avec GraalVM ?<\/h4>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"281\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/frameworkGraal-1-1024x281.png\" alt=\"\" class=\"wp-image-236\" srcset=\"https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/frameworkGraal-1-1024x281.png 1024w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/frameworkGraal-1-300x82.png 300w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/frameworkGraal-1-768x211.png 768w, https:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/frameworkGraal-1.png 1303w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Un gros travail est actuellement men\u00e9 sur Spring pour le rendre totalement compatible.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Pour conclure<\/h2>\n\n\n\n<p>Oracle frappe fort et cr\u00e9e une petite r\u00e9volution en proposant 3 \u00e9volutions majeures.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>L\u2019am\u00e9lioration de sa compilation \u00e0 chaud,<\/li>\n\n\n\n<li>rendre sa Jvm capable d\u2019interpr\u00e9ter plusieurs langages<\/li>\n\n\n\n<li>proposer une solution fiable de compilation native<\/li>\n<\/ul>\n\n\n\n<p>GraalVM a longtemps \u00e9t\u00e9 consid\u00e9r\u00e9e comme une VM exp\u00e9rimentale, ce n\u2019est clairement plus le cas. Les grands frameworks ne s\u2019y sont pas tromp\u00e9s et se rendent petit \u00e0 petit compatible. RedHat a largement particip\u00e9 \u00e0 la popularisation de GraalVM via Quarkus.<\/p>\n\n\n\n<p>De mani\u00e8re globale, Oracle a adopt\u00e9 ces derniers temps une d\u00e9marche beaucoup plus conqu\u00e9rante en terme de d\u00e9veloppement de son langage. Que ce soit par ses travaux sur Graal ou la publication de release tous les 6 mois. Dans un monde ou des langages performants \u00e9mergent r\u00e9guli\u00e8rement tels que Rust ou Go, il est clair qu\u2019il s\u2019agit d\u2019un enjeu strat\u00e9gique pour Oracle de rester leader dans ce domaine.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><a href=\"https:\/\/gitlab.com\/bmeynier\/graalvm-reflection\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/baptiste-meynier.com\/wp-content\/uploads\/2020\/11\/gitlab.png\" alt=\"\" class=\"wp-image-176\" width=\"99\" height=\"91\"\/><\/a><\/figure>\n<\/div>\n\n\n<p class=\"has-text-align-center\"><em>Retrouvez le code source sur Gitlab !<\/em><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Sources:<\/h4>\n\n\n\n<p><a href=\"https:\/\/www.graalvm.org\">https:\/\/www.graalvm.org<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/developer.okta.com\/blog\/2019\/11\/27\/graalvm-java-binaries\">https:\/\/developer.okta.com\/blog\/2019\/11\/27\/graalvm-java-binaries<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/rieckpil.de\/whatis-graalvm\/\">https:\/\/rieckpil.de\/whatis-graalvm\/<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/fr.wikipedia.org\/wiki\/Compilation_%C3%A0_la_vol%C3%A9e\">https:\/\/fr.wikipedia.org\/wiki\/Compilation_%C3%A0_la_vol%C3%A9e<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/www.baeldung.com\/graal-java-jit-compiler\">https:\/\/www.baeldung.com\/graal-java-jit-compiler<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/www.infoq.com\/fr\/articles\/Graal-Java-JIT-Compiler\/\">https:\/\/www.infoq.com\/fr\/articles\/Graal-Java-JIT-Compiler\/<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/www.baeldung.com\/ahead-of-time-compilation\">https:\/\/www.baeldung.com\/ahead-of-time-compilation<\/a><\/p>\n\n\n\n<p><a href=\"http:\/\/macias.info\/entry\/202001051700_graal_reflection.md\">http:\/\/macias.info\/entry\/202001051700_graal_reflection.md<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/vertx.io\/\">https:\/\/vertx.io\/<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/helidon.io\/#\/\">https:\/\/helidon.io\/#\/<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/spark.apache.org\/\">https:\/\/spark.apache.org\/<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/quarkus.io\/\">https:\/\/quarkus.io\/<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/micronaut.io\/\">https:\/\/micronaut.io\/<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/medium.com\/graalvm\/simplifying-native-image-generation-with-maven-plugin-and-embeddable-configuration-d5b283b92f57\">https:\/\/medium.com\/graalvm\/simplifying-native-image-generation-with-maven-plugin-and-embeddable-configuration-d5b283b92f57<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Il y a 25 ans, la soci\u00e9t\u00e9 Sun cr\u00e9ait le langage Java. La jvm n\u2019a cess\u00e9 de gagner en performance et s\u2019enrichir en fonctionnalit\u00e9s. Une grande partie du succ\u00e8s du Java r\u00e9side sur sa portabilit\u00e9 et sa facilit\u00e9 de gestion de la m\u00e9moire avec son garbage collector. Cependant, nous oublions souvent de citer son syst\u00e8me &hellip;<\/p>\n","protected":false},"author":1,"featured_media":223,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[6],"tags":[],"class_list":["post-217","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-jvm"],"_links":{"self":[{"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/posts\/217","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/comments?post=217"}],"version-history":[{"count":14,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/posts\/217\/revisions"}],"predecessor-version":[{"id":1849,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/posts\/217\/revisions\/1849"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/media\/223"}],"wp:attachment":[{"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/media?parent=217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/categories?post=217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/baptiste-meynier.com\/index.php\/wp-json\/wp\/v2\/tags?post=217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}