Nucleus
Performance & nativeGraalVM Native Image

Configuration

Référence du bloc DSL graalvm { } qui configure les builds native-image GraalVM : toolchain, nom d'image, arguments de build, repository de metadata et réglages par OS.

Le bloc graalvm { } à l'intérieur de nucleus.application { } configure les builds native-image GraalVM : la toolchain, le binaire de sortie, les arguments passés à native-image, les métadonnées de reachability et les réglages macOS et Windows. Chaque propriété est paresseuse et typée Property. Le bloc est défini sur JvmApplication, il se place donc à côté de mainClass et nativeDistributions.

Activer une native image

Mettez isEnabled = true. Nucleus provisionne la toolchain pour vous — une configuration minimale ressemble à ceci :

build.gradle.kts
nucleus.application {
    mainClass = "com.example.MainKt"

    graalvm {
        isEnabled = true
        imageName = "myapp"

        // Optionnel : optimise l'image pour la taille au lieu du -O2 par défaut.
        optimization = NativeImageOptimization.SIZE

        metadataRepository {
            enabled = true           // défaut
            version = "1.1.4"        // défaut
            excludedModules.add("com.example:my-lib")
        }
    }
}

Nouveau en 2.1

La toolchain est téléchargée automatiquement (voir plus bas) et utilise par défaut GraalVM Community Edition, march et optimization sont désormais des enums type-safe, et la Profile-Guided Optimization est intégrée. En 2.0, vous installiez vous-même une toolchain GraalVM et passiez les flags de taille via buildArgs.

Provisionner la toolchain

Par défaut, Nucleus télécharge et met en cache GraalVM Community Edition sous <gradle-user-home>/nucleus/graalvm — aucune installation locale ni étape graalvm/setup-graalvm nécessaire. Le téléchargement n'a lieu que lorsqu'une tâche native-image s'exécute réellement : lister les tâches ou synchroniser l'IDE ne télécharge jamais de JDK. Une variable d'environnement GRAALVM_HOME reste prioritaire, à condition qu'elle corresponde à la distribution demandée. Le sous-bloc toolchain { } correspond à GraalvmToolchainSettings.

build.gradle.kts
graalvm {
    toolchain {
        autoDownload = true                              // défaut
        distribution = GraalvmDistribution.COMMUNITY     // défaut
        channel = GraalvmChannel.INNOVATION              // défaut ; LTS pour la ligne à support long terme
        // version = "25"                                // optionnel ; remplace channel
    }
}
PropriétéTypeDéfautNotes
autoDownloadProperty<Boolean>trueMettez false pour résoudre via la machinerie de toolchain de Gradle (javaLanguageVersion / jvmVendor).
distributionProperty<GraalvmDistribution>COMMUNITYCOMMUNITY (GraalVM CE) ou ORACLE (Oracle GraalVM). Voir la note de licence ci-dessous.
channelProperty<GraalvmChannel>INNOVATIONINNOVATION (dernière release) ou LTS. Utilisé uniquement quand version n'est pas défini. S'applique aux deux distributions.
versionProperty<String>non définiRemplace channel. Accepte "25i1", "25", ou une version épinglée "25.0.1".
macosIntelFallbackProperty<Boolean>trueSur les Mac Intel (abandonnés par les deux distributions après 25.0.1), retombe sur BellSoft Liberica NIK.
installDirDirectoryProperty<gradle-user-home>/nucleus/graalvmEmplacement du cache de la toolchain téléchargée.

Choisir une distribution

Oracle GraalVM change vos conditions de redistribution

GraalVM CE est sous licence GPLv2 avec Classpath Exception, qui n'impose aucune restriction sur la distribution au sein d'une application payante. Oracle GraalVM est régi par les GraalVM Free Terms and Conditions (GFTC), qui autorisent l'usage en production et commercial mais ne permettent la redistribution du Program qu'« à condition que vous ne facturiez à vos licenciés aucuns frais associés à cette distribution ou à cet usage ». Nucleus copie des bibliothèques runtime GraalVM (libjvm, libawt, …) à côté de l'exécutable packagé : cette clause s'applique donc à votre bundle. Choisir ORACLE déclenche un warning de build. Relisez les GFTC avant de distribuer une application payante.

Optez pour Oracle GraalVM lorsque vous avez besoin de ses optimisations exclusives — Profile-Guided Optimization, optimization = NativeImageOptimization.LEVEL_3 (-O3), profils inférés par ML, et advancedObfuscation :

build.gradle.kts
graalvm {
    toolchain {
        distribution = GraalvmDistribution.ORACLE
    }
}

Avec la toolchain communautaire par défaut, ces fonctionnalités Oracle se dégradent proprement : -O3, --pgo et -H:AdvancedObfuscation sont ignorés avec un warning au lieu de faire échouer le build, et la tâche runWithPgoInstrument n'est pas enregistrée du tout.

Les répertoires d'installation intègrent la distribution (graalvm-community-jdk-* vs graalvm-jdk-*) : changer de distribution ne réutilise jamais le téléchargement de l'autre, et un GRAALVM_HOME dont la distribution ne correspond pas au DSL est ignoré avec un warning.

Pour builder sur une autre toolchain communautaire (Liberica NIK, Mandrel), pointez GRAALVM_HOME dessus, ou mettez autoDownload = false et choisissez un jvmVendor.

Référence de graalvm

PropriétéTypeDéfautNotes
isEnabledProperty<Boolean>falseInterrupteur principal du build native-image.
imageNameProperty<String>nom du packageNom du binaire de sortie.
marchProperty<NativeImageMarch>par plateformeNATIVE cible le CPU de build ; COMPATIBILITY cible des CPU plus anciens. Non défini, retombe sur COMPATIBILITY, sauf macOS Apple Silicon qui retombe sur NATIVE.
optimizationProperty<NativeImageOptimization>-O2 de native-imageQUICK_BUILD (-Ob), NONE, LEVEL_1..LEVEL_3, SIZE (-Os). LEVEL_3 est réservé à Oracle GraalVM.
allCharsetsProperty<Boolean>falsetrue émet -H:+AddAllCharsets (embarque tous les charsets du JDK ; uniquement pour les encodages hérités).
mlProfileInferenceProperty<Boolean>truefalse émet -H:-MLProfileInference, désactivant la PGO inférée par ML d'Oracle.
advancedObfuscationProperty<Boolean>falsetrue émet -H:AdvancedObfuscation=, renommant les symboles dans le binaire. Oracle GraalVM uniquement ; ignoré avec un warning ailleurs.
autoIncludeResourcesProperty<Boolean>trueEmbarque les ressources propres au projet (et celles des modules project(...)) dans l'image.
maxHeapSizePercentProperty<Int>25Tas max par défaut en pourcentage de la RAM physique. Suit le collecteur choisi (MaximumHeapSizePercent pour Serial/Epsilon, MaxRAMPercentage pour G1).
maxHeapSizeProperty<String>non définiTas max absolu (ex. "2g", "512m"). Prioritaire sur maxHeapSizePercent.
garbageCollectorProperty<NativeImageGarbageCollector>non définiInscrit --gc= (SERIAL, G1, EPSILON). Non défini : Serial de native-image. G1 est Oracle GraalVM + Linux uniquement et se dégrade en warning ailleurs.
buildArgsListProperty<String>videArguments supplémentaires passés à native-image (l'emportent sur les propriétés ci-dessus).
javaLanguageVersionProperty<Int>25Version de langage de la toolchain — utilisée uniquement quand toolchain { autoDownload = false }.
jvmVendorProperty<JvmVendorSpec>non définiVendor de la toolchain — utilisé uniquement quand toolchain { autoDownload = false }.
nativeImageConfigBaseDirDirectoryPropertyRépertoire du reachability-metadata.json spécifique à l'app. Rarement nécessaire.
toolchainGraalvmToolchainSettingstéléchargement autoProvisioning de la toolchain (voir plus haut).
pgoGraalvmPgoSettingsactivéProfile-Guided Optimization (voir plus bas).
macOSGraalvmMacOSSettingsSous-bloc macOS (voir plus bas).
windowsGraalvmWindowsSettingsSous-bloc Windows (voir plus bas).
metadataRepositoryMetadataRepositorySettingsactivéOracle Reachability Metadata Repository (voir plus bas).

Choisir un garbage collector

Le collecteur est fixé au build pour les images natives. Laissez-le non défini pour Serial (le bon défaut pour un tas de taille desktop). Ne choisissez G1 que lorsque le tas dépasse ce que Serial peut collecter sans pauses visibles, et uniquement sous Oracle GraalVM Linux :

build.gradle.kts
nucleus.application {
    // Distribution JVM HotSpot (launcher + tâche run)
    garbageCollector = GarbageCollector.Z

    graalvm {
        // Inscrit dans l'image native (--gc=)
        garbageCollector = NativeImageGarbageCollector.G1
    }
}
NativeImageGarbageCollectorFlagNotes
SERIAL--gc=serialDéfaut. Petits tas, pauses qui croissent avec la taille du tas.
G1--gc=G1Oracle GraalVM + Linux uniquement. Ailleurs : warning + Serial.
EPSILON--gc=epsilonAucune récupération — benchmarks / processus courts uniquement.

Valeurs JVM de GarbageCollector : SERIAL, PARALLEL, G1, Z, SHENANDOAH, EPSILON. Les flags sont préfixés pour qu'un -XX:+Use…GC explicite dans jvmArgs l'emporte encore. Non défini : ergonomie du JDK.

Définir les arguments de build

Les buildArgs sont transmis tels quels à native-image et l'emportent sur les propriétés type-safe. Préférez optimization à un -Os/-O* brut et allCharsets à -H:+AddAllCharsets ; réservez buildArgs à tout ce qui n'a pas de propriété dédiée :

ArgumentRôle
-Djava.awt.headless=falseActive le support GUI, requis pour les apps desktop.
-H:-IncludeMethodDataRetire les métadonnées de méthodes, réduisant le binaire de plusieurs Mo.

Stripping automatique de l'exécutable

Sous Linux et macOS, l'exécutable natif principal est désormais strippé automatiquement, récupérant des dizaines de Mo. Combinez avec optimization = NativeImageOptimization.SIZE pour l'image la plus petite.

Optimiser avec un profil PGO

La Profile-Guided Optimization (Oracle GraalVM uniquement) enregistre la façon dont l'app s'exécute réellement et réinjecte ce profil dans le build suivant. Elle nécessite toolchain { distribution = GraalvmDistribution.ORACLE } ; avec la toolchain communautaire par défaut, runWithPgoInstrument n'est pas enregistrée. Le sous-bloc pgo { } correspond à GraalvmPgoSettings.

build.gradle.kts
graalvm {
    pgo {
        enabled = true                                                    // défaut
        profile = layout.projectDirectory.file("graalvm/pgo/default.iprof") // défaut
    }
}
  1. Enregistrer : ./gradlew runWithPgoInstrument construit une image instrumentée, l'exécute et écrit le profil dans profile à la sortie. Exercez les chemins chauds avant de quitter.
  2. Committez le fichier .iprof. Les builds complets (createGraalvmNativeDistributable, runGraalvmNativeDistributable, tâches de packaging) l'appliquent automatiquement en --pgo=<profile>. Le chemin quick-build runGraalvmNative saute la PGO et l'obfuscation avancée.

Désactivez un profil enregistré pour un seul build avec -Pnucleus.graalvm.pgo=off. Sur les toolchains communautaires (GraalVM CE, Liberica NIK, Mandrel), --pgo n'est pas disponible : un profil enregistré est ignoré avec un avertissement, et la tâche runWithPgoInstrument n'existe pas.

PropriétéTypeDéfautNotes
enabledProperty<Boolean>trueApplique automatiquement le profil quand le fichier existe.
profileRegularFilePropertygraalvm/pgo/default.iprofEmplacement du profil enregistré.

Configurer le repository de metadata

Le plugin Nucleus télécharge l' Oracle GraalVM Reachability Metadata Repository et résout les entrées de chaque dépendance runtime du classpath. Le sous-bloc metadataRepository { } correspond à MetadataRepositorySettings.

PropriétéTypeDéfautNotes
enabledProperty<Boolean>trueMettez false pour ignorer entièrement le repository.
versionProperty<String>"1.1.4"Version de l'artefact du repository.
excludedModulesSetProperty<String>videCoordonnées group:artifact à ignorer.
moduleToConfigVersionMapProperty<String, String>videÉpingle la version du répertoire de metadata pour un module donné.
build.gradle.kts
metadataRepository {
    moduleToConfigVersion.put("io.ktor:ktor-client-core", "3.0.0")
    excludedModules.add("group:noisy-lib")
}

Configurer les réglages macOS

Sous macOS (arm64), les images natives du backend Tao (par défaut) se construisent sur la toolchain auto-provisionnée (GraalVM CE par défaut). Le backend AWT, déprécié, nécessite encore BellSoft Liberica NIK. Les Mac Intel retombent sur Liberica NIK.

Le sous-bloc macOS { } correspond à GraalvmMacOSSettings.

PropriétéTypeDéfautNotes
cStubsSrcRegularFilePropertyFichier de stubs C supplémentaires liés dans le binaire.
minimumSystemVersionProperty<String>"12.0"Corrige la commande de chargement Mach-O LC_VERSION_MIN_MACOSX.
macOsSdkVersionProperty<String>"26.0"Version du SDK estampillée dans les headers Mach-O du launcher, qui détermine l'éligibilité à Liquid Glass.

Configurer les réglages Windows

Le sous-bloc windows { } correspond à GraalvmWindowsSettings. Sur Windows, les native images GraalVM sont liées dynamiquement au runtime Visual C++, qui ne fait pas partie d'une installation Windows propre. Regrouper les DLL du runtime à côté de l'exécutable permet à l'app de démarrer sans le Visual C++ Redistributable.

PropriétéTypeDéfautNotes
bundleCRuntimeProperty<Boolean>trueCopie les DLL du runtime MSVC à côté du .exe.
dllsListProperty<String>vcruntime140.dll, vcruntime140_1.dll, msvcp140.dllNoms des DLL copiées quand bundleCRuntime est activé.
sourceDirDirectoryPropertybin de la toolchainRépertoire d'où les DLL sont copiées. Pointez-le vers le MSVC redistributable si une DLL manque dans la toolchain.
build.gradle.kts
graalvm {
    windows {
        bundleCRuntime = true
        dlls.add("vcruntime140.dll")
    }
}

Pas de variant release

Contrairement aux build types JVM, GraalVM n'a pas de variant release : il n'existe ni packageReleaseGraalvmNative ni runReleaseGraalvmNative. Les tâches natives publiques suivent le pipeline JVM (runGraalvmNative, createGraalvmNativeDistributable, …). C'est volontaire :

  • L'élimination de code mort de ProGuard est redondante. native-image fait déjà une élimination de code mort en monde fermé au moment de la compilation.
  • ProGuard peut renommer des classes encore référencées par reachability-metadata.json, ce qui casse le build silencieusement.

Utilisez optimization = NativeImageOptimization.SIZE pour optimiser la taille plutôt que ProGuard.

nativeImageConfigBaseDir est généralement vide

Nucleus livre automatiquement toutes les métadonnées génériques et spécifiques à la plateforme. Vous n'avez besoin de nativeImageConfigBaseDir que pour les entrées spécifiques à l'app que les couches automatiques ne couvrent pas, ce qui est rare. Voir Metadata automatique pour les cinq couches.

Et ensuite