skip to content

native-gradle-plugin

The Gradle plugin exposes a graalvmNative DSL with compile and run tasks, image name and build arguments, integrated with the Boot plugin. The Gradle counterpart of the same workflow.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

explore

questions

5

What is the GraalVM native-build-tools Gradle plugin, and which tasks does it add to a Spring Boot build?

level: juniorimportance: must knowfreq 55%

answer

  1. org.graalvm.buildtools.native
  2. nativeCompile / nativeRun / nativeTest tasks
  3. graalvmNative DSL
  4. needs GraalVM native-image installed
  5. local binary vs bootBuildImage buildpacks

basics

~10 s

It's the Gradle plugin org.graalvm.buildtools.native that lets you compile a GraalVM native image locally. It adds tasks like nativeCompile (build the native executable) and nativeRun (run it).

solid answer

~30 s

The native-build-tools plugin, applied as `org.graalvm.buildtools.native`, teaches Gradle how to invoke GraalVM's `native-image` tool. It exposes a `graalvmNative` DSL and registers tasks: `nativeCompile` produces a standalone native executable under `build/native/nativeCompile/`, `nativeRun` builds then runs it, and `nativeTest`/`nativeTestCompile` run your tests inside a native image. It needs a GraalVM JDK installed (with `native-image`). With Spring Boot 3, applying this plugin also wires Spring's ahead-of-time processing (`processAot`) so the generated AOT code and reachability hints are compiled into the image. This is distinct from Spring Boot's `bootBuildImage`, which produces a native image via buildpacks in a container instead of locally.

code

kotlin · 12 lines
kotlin
// build.gradle.kts
plugins {
    id("org.springframework.boot") version "3.3.0"
    id("io.spring.dependency-management") version "1.1.5"
    id("org.graalvm.buildtools.native") version "0.10.2"
    kotlin("jvm") version "1.9.24"
}

// Then from the shell (with a GraalVM JDK):
//   ./gradlew nativeCompile   -> build/native/nativeCompile/<app>
//   ./gradlew nativeRun       -> builds + runs the executable
//   ./gradlew nativeTest      -> runs tests inside a native image

go deeper

for a junior

Know the plugin id and that nativeCompile/nativeRun build and run a native executable, and that GraalVM must be installed.

for a middle

Add the DSL name, nativeTest, and the role of Spring's AOT in enabling native builds.

for a senior

Explain the processAot wiring and contrast local nativeCompile with buildpack-based bootBuildImage.

for a principal

Discuss build-time/memory cost, cross-platform binary constraints, and CI strategy for when to run native builds.

## What it is **GraalVM native image** turns a JVM application into a single, ahead-of-time-compiled native executable that starts in milliseconds and uses less memory, at the cost of a slow, closed-world build and no runtime class loading. To build one you invoke GraalVM's `native-image` command-line tool. The **native-build-tools Gradle plugin** (plugin id `org.graalvm.buildtools.native`, group `org.graalvm.buildtools`) is the official bridge that makes Gradle drive `native-image` for you. You apply it in `build.gradle(.kts)`: ```kotlin plugins { id("org.springframework.boot") version "3.x" id("org.graalvm.buildtools.native") version "0.10.x" } ``` ## Tasks it registers - **`nativeCompile`** — runs Spring AOT (via `processAot`), assembles the classpath, and invokes `native-image` to produce a standalone executable in `build/native/nativeCompile/`. - **`nativeRun`** — depends on `nativeCompile`, then executes the produced binary. - **`nativeTestCompile`** — builds a native image of your test suite. - **`nativeTest`** — runs JUnit tests as a native image (verifies the app behaves under closed-world assumptions). - Supporting tasks like `metadataCopy` (for reachability metadata) and `collectReachabilityMetadata`. ## The DSL The plugin adds a `graalvmNative { }` extension used to configure the image (name, build args, debug, etc.) — see the configuration question. ## Prerequisites `native-image` must be available. Either install a GraalVM JDK and let the plugin's **toolchain detection** find it, or set `graalvmNative { toolchainDetection = false }` and run Gradle with a GraalVM `JAVA_HOME`. ## Spring Boot integration Spring Boot's Gradle plugin (3.0+) reacts to the presence of the native plugin: it registers `processAot`/`processTestAot`, which run Spring's `AotProcessor` to generate bytecode-free bean definitions, proxy classes, and `reachability-metadata` (reflection/resource/proxy hints). The native plugin then feeds all of that to `native-image`. Without AOT, a Spring app generally cannot be compiled to native because of its heavy runtime reflection and proxying. ## `nativeCompile` vs `bootBuildImage` Two ways to get a native Spring Boot app: - **`nativeCompile`** (this plugin) — local build, requires a GraalVM JDK, output is a host-OS binary. - **`bootBuildImage`** (Spring Boot plugin, Cloud Native Buildpacks) — containerized build, requires Docker, no local GraalVM needed; Spring Boot auto-sets `BP_NATIVE_IMAGE=true` when the native plugin is applied. Output is an OCI image. ## Gotchas - Native builds are slow (minutes) and memory-hungry — don't run them on every commit. - The binary is OS/arch specific; you must build on (or for) the target platform. - `nativeCompile` fails if `native-image` isn't found — the most common newcomer error.

  • What must be installed on the machine for `nativeCompile` to succeed?
    A GraalVM JDK that includes the `native-image` tool. Either let the plugin's toolchain detection locate it, or run Gradle with a GraalVM `JAVA_HOME`. Without `native-image` on the path, `nativeCompile` fails.
  • How is `nativeCompile` different from `bootBuildImage` for producing a native app?
    `nativeCompile` builds a native binary locally using an installed GraalVM. `bootBuildImage` uses Cloud Native Buildpacks in a Docker container (no local GraalVM needed) and outputs an OCI image; Spring Boot auto-enables native there via `BP_NATIVE_IMAGE=true`.

saying these in an interview costs you the question

  • Thinking `nativeCompile` runs on a plain OpenJDK without GraalVM's native-image
  • Believing the plugin produces a portable JAR rather than an OS/arch-specific binary
  • Confusing `nativeCompile` (local) with `bootBuildImage` (buildpacks/Docker)

context

open as a page

How does the native Gradle plugin integrate with the Spring Boot Gradle plugin's AOT processing to build a native image?

level: seniorimportance: must knowfreq 40%

basics

~20 s

When both plugins are applied, Spring Boot registers processAot, which runs Spring's AOT engine to generate bean-registration code and reachability hints. The native plugin's nativeCompile then depends on that output and feeds it to native-image.

open as a page

How do you configure the output name and pass extra `native-image` flags using the `graalvmNative` DSL?

level: middleimportance: should knowfreq 45%

basics

~10 s

Inside graalvmNative { binaries { named("main") { ... } } } you set imageName.set("my-app") for the executable's name and add native-image flags with buildArgs.add("--verbose").

open as a page

What do the `nativeTest` task and the `metadataRepository` DSL block do, and why do they matter for a Spring Boot native build?

level: middleimportance: should knowfreq 28%

basics

~20 s

nativeTest compiles and runs your JUnit tests as a native image, catching problems (like missing reflection hints) that don't appear on the JVM. metadataRepository { enabled = true } pulls in community-maintained GraalVM hints for third-party libraries so their reflection/resources work in native.

open as a page

You're setting up native image builds in CI for a Spring Boot service. How do you control GraalVM toolchain selection and tune `native-image` behavior via the plugin, and what pitfalls do you plan for?

level: principalimportance: should knowfreq 25%

basics

~20 s

Pin a GraalVM JDK (toolchain detection or a GraalVM JAVA_HOME), keep native builds off the hot path because they're slow and memory-heavy, tune with buildArgs/quickBuild per environment, and validate with nativeTest. Watch for missing hints, cross-platform binaries, and OOM during compilation.

open as a page