Advanced Native Images Topics :: Spring Boot Why Spring Overview Trending Generative AI Cloud Architecture Patterns Microservices Reactive Event Driven Application Types Web Applications Serverless Batch Learn Getting Started Quickstart Guides Academy Courses Get Certified Projects Overview Projects Spring Boot Spring Framework Spring Cloud Spring AI Spring Data Spring Integration Spring Batch Spring Security Foundational Projects Micrometer Reactor Development Tools Spring Tools Spring Initializr Resources Blog Release Calendar Version Mappings Release Highlights Security Advisories GitHub Orgs Spring Projects Spring Cloud Community Overview Events Authors Enterprise Overview Long-term Support Automated Upgrades Governance and Compliance Modern App Development light Spring Boot 4.1.1-SNAPSHOT Search Overview Documentation Community System Requirements Installing Spring Boot Upgrading Spring Boot Tutorials Developing Your First Spring Boot Application Reference Developing with Spring Boot Build Systems Structuring Your Code Configuration Classes Auto-configuration Spring Beans and Dependency Injection Using the @SpringBootApplication Annotation Running Your Application Developer Tools Packaging Your Application for Production Core Features SpringApplication Externalized Configuration Profiles Logging Internationalization Aspect-Oriented Programming JSON Task Execution and Scheduling Development-time Services Creating Your Own Auto-configuration Kotlin Support SSL Web Servlet Web Applications Reactive Web Applications Graceful Shutdown Spring Security Spring Session Spring for GraphQL Spring HATEOAS Data SQL Databases Working with NoSQL Technologies IO Caching Spring Batch gRPC Hazelcast Quartz Scheduler Sending Email Validation Calling REST Services Web Services Distributed Transactions With JTA Messaging JMS AMQP Apache Kafka Support Apache Pulsar Support RSocket Spring Integration WebSockets Security OAuth2 SAML 2.0 Testing Test Modules Test Scope Dependencies Testing Spring Applications Testing Spring Boot Applications Testcontainers Test Utilities Packaging Spring Boot Applications Efficient Deployments AOT Cache Ahead-of-Time Processing With the JVM GraalVM Native Images Introducing GraalVM Native Images Advanced Native Images Topics Checkpoint and Restore With the JVM Container Images Efficient Container Images Dockerfiles Cloud Native Buildpacks Production-ready Features Enabling Production-ready Features Endpoints Monitoring and Management Over HTTP Monitoring and Management over JMX Observability Loggers Metrics Tracing Auditing Recording HTTP Exchanges Process Monitoring Cloud Foundry Support How-to Guides Spring Boot Application Properties and Configuration Embedded Web Servers Spring MVC Jersey HTTP Clients Logging Data Access Database Initialization NoSQL Messaging Batch Applications Actuator Security Hot Swapping Testing Build Ahead-of-Time Processing GraalVM Native Applications Developing Your First GraalVM Native Application Testing GraalVM Native Images AOT Cache Deploying Spring Boot Applications Traditional Deployment Deploying to the Cloud Installing Spring Boot Applications Docker Compose Build Tool Plugins Maven Plugin Getting Started Using the Plugin Goals Packaging Executable Archives Packaging OCI Images Running your Application with Maven Ahead-of-Time Processing Running Integration Tests Integrating with Actuator Help Information Gradle Plugin Getting Started Managing Dependencies Packaging Executable Archives Packaging OCI Images Publishing your Application Running your Application with Gradle Ahead-of-Time Processing Integrating with Actuator Reacting to Other Plugins Spring Boot AntLib Module Supporting Other Build Systems Spring Boot CLI Installing the CLI Using the CLI Rest APIs Actuator Audit Events (auditevents) Beans (beans) Caches (caches) Conditions Evaluation Report (conditions) Configuration Properties (configprops) Environment (env) Flyway (flyway) Health (health) Heap Dump (heapdump) HTTP Exchanges (httpexchanges) Info (info) Spring Integration Graph (integrationgraph) Liquibase (liquibase) Log File (logfile) Loggers (loggers) Mappings (mappings) Metrics (metrics) Prometheus (prometheus) Quartz (quartz) Software Bill of Materials (sbom) Scheduled Tasks (scheduledtasks) Sessions (sessions) Shutdown (shutdown) Application Startup (startup) Thread Dump (threaddump) Java APIs Spring Boot Gradle Plugin Maven Plugin Kotlin APIs Spring Boot Specifications Configuration Metadata Metadata Format Providing Manual Hints Generating Your Own Metadata by Using the Annotation Processor The Executable Jar Format Nested JARs Spring Boot’s “NestedJarFile” Class Launching Executable Jars PropertiesLauncher Features Executable Jar Restrictions Alternative Single Jar Solutions Appendix Common Application Properties Deprecated Application Properties Auto-configuration Classes spring-boot-activemq spring-boot-actuator-autoconfigure spring-boot-amqp spring-boot-artemis spring-boot-autoconfigure spring-boot-batch spring-boot-batch-data-mongodb spring-boot-batch-jdbc spring-boot-cache spring-boot-cassandra spring-boot-cloudfoundry spring-boot-couchbase spring-boot-data-cassandra spring-boot-data-commons spring-boot-data-couchbase spring-boot-data-elasticsearch spring-boot-data-jdbc spring-boot-data-jpa spring-boot-data-ldap spring-boot-data-mongodb spring-boot-data-neo4j spring-boot-data-r2dbc spring-boot-data-redis spring-boot-data-rest spring-boot-devtools spring-boot-elasticsearch spring-boot-flyway spring-boot-freemarker spring-boot-graphql spring-boot-groovy-templates spring-boot-grpc-client spring-boot-grpc-server spring-boot-gson spring-boot-h2console spring-boot-hateoas spring-boot-hazelcast spring-boot-health spring-boot-hibernate spring-boot-http-client spring-boot-http-codec spring-boot-http-converter spring-boot-integration spring-boot-jackson spring-boot-jackson2 spring-boot-jdbc spring-boot-jersey spring-boot-jetty spring-boot-jms spring-boot-jooq spring-boot-jsonb spring-boot-kafka spring-boot-kotlinx-serialization-json spring-boot-ldap spring-boot-liquibase spring-boot-mail spring-boot-micrometer-metrics spring-boot-micrometer-observation spring-boot-micrometer-tracing spring-boot-micrometer-tracing-brave spring-boot-micrometer-tracing-opentelemetry spring-boot-mongodb spring-boot-mustache spring-boot-neo4j spring-boot-netty spring-boot-opentelemetry spring-boot-persistence spring-boot-pulsar spring-boot-quartz spring-boot-r2dbc spring-boot-reactor spring-boot-reactor-netty spring-boot-restclient spring-boot-resttestclient spring-boot-rsocket spring-boot-security spring-boot-security-oauth2-authorization-server spring-boot-security-oauth2-client spring-boot-security-oauth2-resource-server spring-boot-security-saml2 spring-boot-sendgrid spring-boot-servlet spring-boot-session spring-boot-session-data-redis spring-boot-session-jdbc spring-boot-testcontainers spring-boot-thymeleaf spring-boot-tomcat spring-boot-transaction spring-boot-validation spring-boot-webclient spring-boot-webflux spring-boot-webmvc spring-boot-webservices spring-boot-websocket spring-boot-zipkin Test Auto-configuration Annotations Test Slices Dependency Versions Managed Dependency Coordinates Version Properties Search Edit this Page GitHub Project Stack Overflow Spring Boot Reference Packaging Spring Boot Applications GraalVM Native Images Advanced Native Images Topics This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Boot 4.1.0! Advanced Native Images Topics Nested Configuration Properties Reflection hints are automatically created for configuration properties by the Spring ahead-of-time engine. Nested configuration properties which are not inner classes, however, must be annotated with @NestedConfigurationProperty, otherwise they won’t be detected and will not be bindable. import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; @ConfigurationProperties("my.properties") public class MyProperties { private String name; @NestedConfigurationProperty private final Nested nested = new Nested(); // getters / setters... public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Nested getNested() { return this.nested; } } where Nested is: Java Kotlin public class Nested { private int number; // getters / setters... public int getNumber() { return this.number; } public void setNumber(int number) { this.number = number; } } class Nested { } The example above produces configuration properties for my.properties.name and my.properties.nested.number. Without the @NestedConfigurationProperty annotation on the nested field, the my.properties.nested.number property would not be bindable in a native image. You can also annotate the getter method. When using constructor binding, you have to annotate the field with @NestedConfigurationProperty: import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; @ConfigurationProperties("my.properties") public class MyPropertiesCtor { private final String name; @NestedConfigurationProperty private final Nested nested; public MyPropertiesCtor(String name, Nested nested) { this.name = name; this.nested = nested; } // getters / setters... public String getName() { return this.name; } public Nested getNested() { return this.nested; } } When using records, you have to annotate the parameter with @NestedConfigurationProperty: import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; @ConfigurationProperties("my.properties") public record MyPropertiesRecord(String name, @NestedConfigurationProperty Nested nested) { } When using Kotlin, you need to annotate the parameter of a data class with @NestedConfigurationProperty: import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.boot.context.properties.NestedConfigurationProperty @ConfigurationProperties("my.properties") data class MyPropertiesKotlin( val name: String, @NestedConfigurationProperty val nested: Nested ) Please use public getters and setters in all cases, otherwise the properties will not be bindable. Converting a Spring Boot Executable Jar It is possible to convert a Spring Boot executable jar into a native image as long as the jar contains the AOT generated assets. This can be useful for a number of reasons, including: You can keep your regular JVM pipeline and turn the JVM application into a native image on your CI/CD platform. As native-image does not support cross-compilation, you can keep an OS neutral deployment artifact which you convert later to different OS architectures. You can convert a Spring Boot executable jar into a native image using Cloud Native Buildpacks, or using the native-image tool that is shipped with GraalVM. Your executable jar must include AOT generated assets such as generated classes and JSON hint files. Using Buildpacks Spring Boot applications usually use Cloud Native Buildpacks through the Maven (mvn spring-boot:build-image) or Gradle (gradle bootBuildImage) integrations. You can, however, also use pack to turn an AOT processed Spring Boot executable jar into a native container image. You have to build your application with at least JDK 25, because Buildpacks use the same GraalVM native-image version as the Java version used for compilation. First, make sure that a Docker daemon is available (see Get Docker for more details). Configure it to allow non-root user if you are on Linux. You also need to install pack by following the installation guide on buildpacks.io. Assuming an AOT processed Spring Boot executable jar built as myproject-0.0.1-SNAPSHOT.jar is in the target directory, run: $ pack build --builder paketobuildpacks/builder-noble-java-tiny \ --path target/myproject-0.0.1-SNAPSHOT.jar \ --env 'BP_NATIVE_IMAGE=true' \ my-application:0.0.1-SNAPSHOT You do not need to have a local GraalVM installation to generate an image in this way. Once pack has finished, you can launch the application using docker run: $ docker run --rm -p 8080:8080 docker.io/library/myproject:0.0.1-SNAPSHOT Using GraalVM native-image Another option to turn an AOT processed Spring Boot executable jar into a native executable is to use the GraalVM native-image tool. For this to work, you’ll need a GraalVM distribution on your machine. You can either download it manually on the Liberica Native Image Kit page or you can use a download manager like SDKMAN!. Assuming an AOT processed Spring Boot executable jar built as myproject-0.0.1-SNAPSHOT.jar is in the target directory, run: $ rm -rf target/native $ mkdir -p target/native $ cd target/native $ jar -xvf ../myproject-0.0.1-SNAPSHOT.jar $ native-image -H:Name=myproject @META-INF/native-image/argfile -cp .:BOOT-INF/classes:`find BOOT-INF/lib | tr '\n' ':'` $ mv myproject ../ These commands work on Linux or macOS machines, but you will need to adapt them for Windows. The @META-INF/native-image/argfile might not be packaged in your jar. It is only included when reachability metadata overrides are needed. The native-image -cp flag does not accept wildcards. You need to ensure that all jars are listed (the command above uses find and tr to do this). Using the Tracing Agent The GraalVM native image tracing agent allows you to intercept reflection, resources or proxy usage on the JVM in order to generate the related hints. Spring should generate most of these hints automatically, but the tracing agent can be used to quickly identify the missing entries. When using the agent to generate hints for a native image, there are a couple of approaches: Launch the application directly and exercise it. Run application tests to exercise the application. The first option is interesting for identifying the missing hints when a library or a pattern is not recognized by Spring. The second option sounds more appealing for a repeatable setup, but by default the generated hints will include anything required by the test infrastructure. Some of these will be unnecessary when the application runs for real. To address this problem the agent supports an access-filter file that will cause certain data to be excluded from the generated output. Launch the Application Directly Use the following command to launch the application with the native image tracing agent attached: $ java -Dspring.aot.enabled=true \ -agentlib:native-image-agent=config-output-dir=/path/to/config-dir/ \ -jar target/myproject-0.0.1-SNAPSHOT.jar Now you can exercise the code paths you want to have hints for and then stop the application with ctrl-c. On application shutdown the native image tracing agent will write the hint files to the given config output directory. You can either manually inspect these files, or use them as input to the native image build process. To use them as input, copy them into the src/main/resources/META-INF/native-image/ directory. The next time you build the native image, GraalVM will take these files into consideration. There are more advanced options which can be set on the native image tracing agent, for example filtering the recorded hints by caller classes, etc. For further reading, please see the official documentation. Custom Hints If you need to provide your own hints for reflection, resources, serialization, proxy usage and so on, you can use the RuntimeHintsRegistrar API. Create a class that implements the RuntimeHintsRegistrar interface, and then make appropriate calls to the provided RuntimeHints instance: import java.lang.reflect.Method; import org.springframework.aot.hint.ExecutableMode; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.util.ReflectionUtils; public class MyRuntimeHints implements RuntimeHintsRegistrar { @Override public void registerHints(RuntimeHints hints, ClassLoader classLoader) { // Register method for reflection Method method = ReflectionUtils.findMethod(MyClass.class, "sayHello", String.class); hints.reflection().registerMethod(method, ExecutableMode.INVOKE); // Register type for java serialization hints.reflection().registerJavaSerialization(MySerializableClass.class); // Register resources hints.resources().registerPattern("my-resource.txt"); // Register proxy hints.proxies().registerJdkProxy(MyInterface.class); } } You can then use @ImportRuntimeHints on any @Configuration class (for example your @SpringBootApplication annotated application class) to activate those hints. If you have classes which need binding (mostly needed when serializing or deserializing JSON), you can use @RegisterReflectionForBinding on any bean. Most of the hints are automatically inferred, for example when accepting or returning data from a @RestController method. But when you work with WebClient, RestClient or RestTemplate directly, you might need to use @RegisterReflectionForBinding. Testing Custom Hints The RuntimeHintsPredicates API can be used to test your hints. The API provides methods that build a Predicate that can be used to test a RuntimeHints instance. If you’re using AssertJ, your test would look like this: import org.junit.jupiter.api.Test; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; import org.springframework.boot.docs.packaging.nativeimage.advanced.customhints.MyRuntimeHints; import static org.assertj.core.api.Assertions.assertThat; class MyRuntimeHintsTests { @Test void shouldRegisterHints() { RuntimeHints hints = new RuntimeHints(); new MyRuntimeHints().registerHints(hints, getClass().getClassLoader()); assertThat(RuntimeHintsPredicates.resource().forResource("my-resource.txt")).accepts(hints); } } Providing Hints Statically If you prefer, custom hints can be provided statically in one or more GraalVM JSON hint files. Such files should be placed in src/main/resources/ within a META-INF/native-image/*/*/ directory. The hints generated during AOT processing are written to a directory named META-INF/native-image/{groupId}/{artifactId}/. Place your static hint files in a directory that does not clash with this location, such as META-INF/native-image/{groupId}/{artifactId}-additional-hints/. Known Limitations GraalVM native images are an evolving technology and not all libraries provide support. The GraalVM community is helping by providing reachability metadata for projects that don’t yet ship their own. Spring itself doesn’t contain hints for 3rd party libraries and instead relies on the reachability metadata project. If you encounter problems when generating native images for Spring Boot applications, please check the Spring Boot with GraalVM page of the Spring Boot wiki. You can also contribute issues to the spring-aot-smoke-tests project on GitHub which is used to confirm that common application types are working as expected. If you find a library which doesn’t work with GraalVM, please raise an issue on the reachability metadata project. Introducing GraalVM Native Images Checkpoint and Restore With the JVM Spring Boot Stable 4.1.0 4.0.7 3.5.16 3.4.13 3.3.13 Snapshot 4.2.0-SNAPSHOT 4.1.1-SNAPSHOT 4.0.8-SNAPSHOT Related Spring Documentation Spring Boot Spring Framework Spring Cloud Spring Cloud Build Spring Cloud Bus Spring Cloud Circuit Breaker Spring Cloud Commons Spring Cloud Config Spring Cloud Consul Spring Cloud Contract Spring Cloud Function Spring Cloud Gateway Spring Cloud Kubernetes Spring Cloud Netflix Spring Cloud OpenFeign Spring Cloud Stream Spring Cloud Task Spring Cloud Vault Spring Cloud Zookeeper Spring Data Spring Data Cassandra Spring Data Commons Spring Data Couchbase Spring Data Elasticsearch Spring Data JPA Spring Data KeyValue Spring Data LDAP Spring Data MongoDB Spring Data Neo4j Spring Data Redis Spring Data JDBC & R2DBC Spring Data REST Spring Integration Spring Batch Spring Security Spring Authorization Server Spring LDAP Spring Security Kerberos Spring Session Spring Vault Spring AI Spring AMQP Spring CLI Spring GraphQL Spring for Apache Kafka Spring Modulith Spring for Apache Pulsar Spring Shell All Docs... Copyright © 2005 - Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. Terms of Use • Privacy • Trademark Guidelines • Thank you • Your California Privacy Rights • Cookie Settings Apache®, Apache Tomcat®, Apache Kafka®, Apache Cassandra™, and Apache Geode™ are trademarks or registered trademarks of the Apache Software Foundation in the United States and/or other countries. Java™, Java™ SE, Java™ EE, and OpenJDK™ are trademarks of Oracle and/or its affiliates. Kubernetes® is a registered trademark of the Linux Foundation in the United States and other countries. Linux® is the registered trademark of Linus Torvalds in the United States and other countries. Windows® and Microsoft® Azure are registered trademarks of Microsoft Corporation. “AWS” and “Amazon Web Services” are trademarks or registered trademarks of Amazon.com Inc. or its affiliates. All other trademarks and copyrights are property of their respective owners and are only mentioned for informative purposes. Other names may be trademarks of their respective owners. Search in all Spring Docs