Côté Linux :
sudo apt-get install build-essential libz-dev zlib1g-dev
Côté GraalVM :
Faire pointer les variables d'environnements JAVA_HOME et GRAALVM_HOME vers le répertoire d'installation de GraalVM.
$GRAALVM_HOME/bin/gu native-image
Enjoy...
Compiler en natif Jooby avec GraalVM.
Je me note la commande :
native-image -H:+ReportExceptionStackTraces -H:+TraceClassInitialization --no-fallback --allow-incomplete-classpath --initialize-at-build-time=io.jooby --initialize-at-build-time=org.slf4j --initialize-at-build-time=ch.qos.logback -jar someJarWithAMainClass.jar
Edit : comme la commande ne marche pas bien, voici un tuto qui montre la démarche à adopter avec Javalin.
Edit 2 : GraalVM est en mesure d'identifier les classes à charger au Runtime à partir d'un agent de la JVM. Ce tuto qui montre l'exemple est fait pour Quarkus mais devrait s'adapter à d'autres serveurs.
Très simple :
- Vous installez GraalVM en tant que JAVA_HOME.
- Vous installez native-image dans GraalVM via la commande
gu install native-image
. - Vous installer les GCC + build-essential :
sudo apt install gcc build-essential
- Vous ajoutez le plugin Maven dans votre projet.
Enjoy :D
Quelques trucs & astuces bien pratiques pour compiler vos applications Kotlin, Scala, Java, Ruby ou encore NodeJS en natif à l'aide de GraalVM.
Visiblement ça marche, sauf dans les cas tricky où il y a une imbrication de la détection des types au runtime. Je note aussi que pour tout ce qui est découverte du classpath au runtime (typiquement les drivers JDBC), il faut spécifier le nom de la classe du driver si elle est chargée via un Class.forName()
(ce qui est toujours le cas en théorie).
Il ne me reste plus que deux questions en suspend avant de pouvoir passer entièrement sous GraalVM :
1) Comment fonctionne le classpath lorsque ce dernier contient un répertoire ? Le contenu est-il intégré à l'exécutable produit par GraalVM ou faut-il faire une bidouille ?
2) Comment fonctionne l'allocation mémoire avec un exécutable natif ? Avant, nous passions les options Xms et Xmx à la JVM mais celles-ci ont-elles encore une sens ?
Sinon les gains au démarrage sont encore plus impressionnant que ceux que j'avais obtenus il y a presque deux ans et l'API NIO est bien plus rapide que celle d'une JVM normale !
Le renouveau de la JVM est bel et bien en train de devenir plus rapide que Go sauf que la plateforme est riche (en termes de features proposées par le langage) et aussi polyglotte puisque GraalVM permet de traiter du Kotlin, du Scala, du R, du JavaScript, du Ruby, etc.
Voilà la solution :
<plugin>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>native-image-maven-plugin</artifactId>
<version>19.3.0</version>
<executions>
<execution>
<goals><goal>native-image</goal></goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<skip>false</skip>
<buildArgs> --no-fallback </buildArgs>
</configuration>
</plugin>
Si votre variable JAVA_HOME
est égale à GRAALVM_HOME
alors cette configuration Maven suffit :
<plugin>
<groupId>com.oracle.substratevm</groupId>
<artifactId>native-image-maven-plugin</artifactId>
<version>1.0.0-rc14</version>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
I'm sooo happy :D Nous allons enfin avoir des applications tournant sur JVM ayant de performances comparables à celles de Go.
Je viens de découvrir que le projet Eclipse fournit un JDK avec compilation AOT et optimisation du binaire via le projet AdoptOpenJDK.
A approfondir.
Je me note la dépendance :
<dependency>
<groupId>com.oracle.substratevm</groupId>
<artifactId>svm</artifactId>
<version>1.0.0-rc8</version>
<scope>provided</scope>
</dependency>
Il faudra que je fasse un poc à ce sujet.
L'avenir de Java est au natif et à la compilation AOT. Je surveille GraalVM depuis presque une année et j'ai déjà fait des présentations dessus. Autant vous dire qu'avec ma migration vers Kotlin, j'attends la première release de GraalVM avec impatience.
Un lien vers la page de Quarkus.
Running Javalin on GraalVM (22MB total size) - Javalin - A lightweight Java and Kotlin web framework
Compiler en natif des jar Java avec GraalVM et le mode ahead-of-time (AOT).
Ce que je note :
- GraalVM ne peut pas gérer de la réflection puisqu'elle a besoin de toutes les classes pour créer un exécutable autoporteur.
- Dans ce cas il faut lui indiquer explicitement les classes à inclure (celles chargée via réflection) lors de la compilation.
La question encore en suspend est : comment fonctionne la gestion de la mémoire de GraalVM mais côté ops, eux qui avaient avant les options -Xms et -Xmx ?
Je m'intéresse beaucoup à GraalVM, ceci d'autant plus que la licence de Java changera au 1er janvier 2019.
Ce faisant, j'ai déjà migré les projets de la boite vers Kotlin afin de nous dissocier du langage Java et quelques temps je pourrai aussi me séparer aussi de la JVM et donc d'Oracle.
Alors je sais bien que GraalVM provient des labos d'Oracle, mais la licence d'utilisation ne pourra pas nous rendre captif puisque GraalVM offre la possibilité de générer un exécutable natif d'une part, et que le compilateur se trouve déjà sous GitHub avec une licence de logiciel libre d'autre part.
L'autre option, c'est Rust, mais Kotlin est plus facile d'accès lorsque l'on vient du monde Java.
J'ai testé ce soir et ce fût un fail. Mais je recommancerai à partir de la première release. Je pense qu'une stack mixée entre Kotlin > bytecode > native peut devenir très intéressant. Et si on se rapproche des tailles d'occupation de la mémoire de Go pour des applications Java-like qui dispose de la même charge CPU, alors autant vous dire que je signe tout de suite !
Edit : j'ai retesté et GraalVM ne supporte pas les accents / espaces dans les chemins de fichiers (y compris celui où elle est installée). Bref ça marche bien et le gain en performance est miraculeux !