Le JEP 544 introduit la compilation Ahead-of-Time native dans la JVM HotSpot
L'écosystème Java franchit une étape importante avec le JEP 544, qui apporte la compilation Ahead-of-Time (AOT) directement au sein de la machine virtuelle HotSpot. En stockant du code natif pré-compilé lors d'une phase d'entraînement, HotSpot réduit drastiquement les temps de démarrage et de chauffe tout en conservant l'agilité de la compilation dynamique.
Fil « Proposition du JEP 544 pour la compilation Ahead-of-Time native dans OpenJDK »
La fin du dilemme entre JIT et compilation statique
Dans l'architecture classique de la machine virtuelle Java HotSpot, une application traverse trois étapes lors de son exécution : le démarrage (interprétation lente du bytecode), le réchauffement (profilage des méthodes fréquemment appelées, dites « hot spots », puis compilation par le compilateur C1) et le régime de croisière (optimisation poussée via le compilateur C2). Cette phase de réchauffement consomme des ressources processeur et mémoire cruciales au lancement.
Le JEP 544 (JDK Enhancement Proposal, un document formel de proposition d'évolution de la plateforme Java) vise à éliminer cette charge initiale en combinant les avantages de la compilation Ahead-of-Time (AOT, la compilation en code natif effectuée avant l'exécution) et du compilateur Just-in-Time (JIT, la compilation à la volée durant l'exécution). Contrairement aux outils d'image native statique qui imposent des contraintes fortes (fermeture du monde, restrictions sur la réflexion dynamiques et le chargement de classes), cette approche conserve 100 % de la dynamique et de la portabilité du langage Java.
Un fonctionnement basé sur une exécution d'entraînement
Développé dans le cadre du projet Leyden, le JEP 544 s'appuie sur les fondations posées par le JEP 483 dans JDK 24 (chargement et liaison AOT des classes) et le JEP 515 dans JDK 25 (profilage AOT des méthodes). Il permet d'enregistrer le code natif compilé par C1 et C2 directement dans un fichier de cache lors d'une première phase d'entraînement (training run).
Pour générer ce cache d'exécution, la commande utilise une simple option au niveau du dictionnaire d'options HotSpot :
java -XX:AOTCacheOutput=app.aot -cp app.jar com.example.App
En environnement de production, l'application est lancée en chargeant ce cache binaire :
java -XX:AOTCache=app.aot -cp app.jar com.example.App
Si le comportement ou la charge applicative change en production, HotSpot peut à tout moment dé-optimiser (deoptimize) le code pré-compilé pour re-passer en JIT et s'adapter aux nouveaux profils d'exécution. Le code AOT et le code JIT coexistent en toute transparence.
Des performances optimisées pour les architectures microservices
Les métriques collectées sur des environnements conteneurisés de 2 vCPU (processeurs virtuels) montrent des gains significatifs pour les architectures microservices où le processeur est très sollicité au démarrage. Sans le code AOT, le simple cache de classes réduisait le temps de démarrage de 50 % à 70 %. Avec le code natif du JEP 544, cette réduction atteint désormais 65 % à 80 %.
Sur des benchmarks d'outillage (comme la compilation répétée via javac), la première itération affiche une amélioration du temps d'exécution allant jusqu'à 75 %.
Le dispositif supporte dès sa proposition les architectures x64 et AArch64 (ARM 64 bits), ainsi que l'ensemble des ramasse-miettes majeurs de HotSpot : Serial, Parallel, G1 et ZGC (Z Garbage Collector). Aucune modification de code ou de bibliothèque n'est nécessaire pour en bénéficier.