GraalVM Native Images are standalone, platform-specific executables produced by compiling a Java application ahead-of-time. Unlike a JVM application, a native image bundles everything it needs — no separate JVM installation is required at runtime. The result typically starts faster and uses less memory, making native images especially attractive for containerized workloads and serverless (FaaS) platforms.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/spring-projects/spring-boot/llms.txt
Use this file to discover all available pages before exploring further.
How native images differ from JVM deployments
Native image compilation applies a closed-world assumption: only code reachable from themain entry point is included in the executable. This unlocks significant runtime efficiency gains but also introduces constraints that JVM deployments do not have.
Static analysis at build time
Static analysis at build time
The GraalVM compiler analyses your application from the
main entry point at build time. Code that is unreachable from that entry point is excluded from the final executable entirely.Fixed classpath
Fixed classpath
The application classpath is determined at build time and cannot change at runtime. Dynamic class loading is not supported.
No lazy class loading
No lazy class loading
All classes shipped in the executable are loaded into memory at startup. There is no on-demand class loading as you find in a standard JVM.
Dynamic features require hints
Dynamic features require hints
GraalVM is not directly aware of reflection, resource loading, serialization, or dynamic proxies. Spring’s AOT processing generates the required hint files automatically for most cases, but you may need to supply additional hints for third-party code.
Bean definitions are fixed at build time
Bean definitions are fixed at build time
Spring’s AOT processing converts
@Configuration classes and @Bean methods into direct source code at build time. As a result:@Profileannotations and profile-specific configuration have limitations.- Condition-driven beans such as those using
@ConditionalOnPropertyand.enabledproperties are not supported at runtime.
Requirements
- GraalVM 22+ (or a compatible distribution such as Liberica Native Image Kit)
- The
native-imagetool installed and available onPATH - Java 17 or later (Java 21+ recommended)
Building a native image
Add the native build plugin
The Spring Boot parent POM and Gradle plugin include a
native profile / task out of the box when you use the Spring Boot starter. Verify your build file includes the native tools plugin.- Maven
- Gradle
Compile the native image
Run the native compilation from your project root. This triggers Spring’s AOT processing and then invokes GraalVM’s The compilation can take several minutes. The resulting native executable is placed in:
native-image tool.- Maven
- Gradle
- Maven:
target/<artifact-name> - Gradle:
build/native/nativeCompile/<artifact-name>
Building a native container image with Buildpacks
If you prefer a Docker-based workflow, Cloud Native Buildpacks can compile a native image inside a container. This means you do not need a local GraalVM installation.You must build your application with at least JDK 25, because Buildpacks use the same GraalVM
native-image version as the Java version used for compilation.- Maven
- Gradle
pack:
What works differently in native mode
Reflection and resource hints
Spring AOT automatically generates GraalVM hint files underMETA-INF/native-image/{groupId}/{artifactId}/ for the reflection, resource, serialization, proxy, and JNI usage it can detect. For code paths Spring cannot discover statically, you register hints manually using RuntimeHintsRegistrar.
See Ahead-of-Time processing for how to write custom hints with @ImportRuntimeHints and RuntimeHintsRegistrar.
Nested configuration properties
Reflection hints for@ConfigurationProperties classes are generated automatically. However, nested configuration property types that are not inner classes must be annotated with @NestedConfigurationProperty, or they will not be bindable in native mode.
@NestedConfigurationProperty on the nested field, my.properties.nested.number would not be bindable when running as a native image.
Using the GraalVM tracing agent
When hints are missing, the GraalVM tracing agent can intercept reflection and resource usage on the JVM and generate the corresponding hint files automatically:src/main/resources/META-INF/native-image/. GraalVM picks them up on the next native compilation.
Testing native images
Run native tests with Maven
Run native tests with Maven
Run native tests with Gradle
Run native tests with Gradle
Convert an existing JAR to a native image manually
Convert an existing JAR to a native image manually
If you already have an AOT-processed executable JAR, you can convert it using the
native-image tool directly (Linux/macOS):Known limitations
GraalVM native image support is continuously evolving. Not all third-party libraries provide native-image-compatible metadata. The GraalVM Reachability Metadata repository community maintains metadata for libraries that do not yet ship their own.Report an issue
The
spring-aot-smoke-tests project tracks common application types. Contribute failing scenarios here.Missing library metadata
If a third-party library doesn’t work with GraalVM, raise an issue in the reachability metadata project.