Ahead-of-Time Processing

Spring AOT is a process that analyzes your application at build-time and generate an optimized version of it. It is a mandatory step to run a Spring ApplicationContext in a native image.

For an overview of GraalVM Native Images support in Spring Boot, check the reference documentation.

The Spring Boot Maven plugin offers goals that can be used to perform AOT processing on both application and test code.

Processing Applications

To configure your application to use this feature, add an execution for the process-aot goal, as shown in the following example:

<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
	<executions>
		<execution>
			<id>process-aot</id>
			<goals>
				<goal>process-aot</goal>
			</goals>
		</execution>
	</executions>
</plugin>

As the BeanFactory is fully prepared at build-time, conditions are also evaluated. This has an important difference compared to what a regular Spring Boot application does at runtime. For instance, if you want to opt-in or opt-out for certain features, you need to configure the environment used at build time to do so. The process-aot goal shares a number of properties with the run goal for that reason.

Using the Native Profile

If you use spring-boot-starter-parent as the parent of your project, a native profile can be used to streamline the steps required to build a native image.

The native profile configures the following:

  • Execution of process-aot when the Spring Boot Maven Plugin is applied on a project.

  • Suitable settings so that build-image generates a native image.

  • Sensible defaults for the Native Build Tools Maven Plugin, in particular:

    • Making sure the plugin uses the raw classpath, and not the main jar file as it does not understand our repackaged jar format.

    • Validate that a suitable GraalVM version is available.

    • Download third-party reachability metadata.

The use of the raw classpath means that native image does not know about the generated MANIFEST. If you need to read the content of the manifest in a native image, for instance to get the implementation version of your application, configure the classesDirectory option to use the regular jar.

To benefit from the native profile, a module that represents an application should define two plugins, as shown in the following example:

<plugin>
	<groupId>org.graalvm.buildtools</groupId>
	<artifactId>native-maven-plugin</artifactId>
</plugin>
<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

A single project can trigger the generation of a native image on the command-line using either Cloud Native Buildpacks or Native Image Build Tools.

To use the native profile with a multi-modules project, you can create a customization of the native profile so that it invokes your preferred technique.

To bind Cloud Native Buildpacks during the package phase, add the following to the root POM of your multi-modules project:

<profile>
	<id>native</id>
	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-maven-plugin</artifactId>
					<executions>
						<execution>
							<id>build-image</id>
							<goals>
								<goal>build-image-no-fork</goal>
							</goals>
						</execution>
					</executions>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</profile>

The example below does the same for Native Build Tools:

<profile>
	<id>native</id>
	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.graalvm.buildtools</groupId>
					<artifactId>native-maven-plugin</artifactId>
					<executions>
						<execution>
							<id>build-image</id>
							<goals>
								<goal>compile-no-fork</goal>
							</goals>
						</execution>
					</executions>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</profile>

Once the above is in place, you can build your multi-modules project and generate a native image in the relevant sub-modules, as shown in the following example:

$ mvn package -Pnative
A "relevant" sub-module is a module that represents a Spring Boot application. Such module must define the Native Build Tools and Spring Boot plugins as described above.

spring-boot:process-aot

org.springframework.boot:spring-boot-maven-plugin:3.3.5

Invoke the AOT engine on the application.

Required parameters

Name Type Default

classesDirectory

File

${project.build.outputDirectory}

generatedClasses

File

${project.build.directory}/spring-aot/main/classes

generatedResources

File

${project.build.directory}/spring-aot/main/resources

generatedSources

File

${project.build.directory}/spring-aot/main/sources

Optional parameters

Name Type Default

arguments

String[]

compilerArguments

String

excludeGroupIds

String

excludes

List

includes

List

jvmArguments

String

mainClass

String

profiles

String[]

skip

boolean

false

systemPropertyVariables

Map

Parameter details

arguments

Application arguments that should be taken into account for AOT processing.

Name

arguments

Type

java.lang.String[]

Default value

User property

Since

classesDirectory

Directory containing the classes and resource files that should be packaged into the archive.

Name

classesDirectory

Type

java.io.File

Default value

${project.build.outputDirectory}

User property

Since

compilerArguments

Arguments that should be provided to the AOT compile process. On command line, make sure to wrap multiple values between quotes.

Name

compilerArguments

Type

java.lang.String

Default value

User property

spring-boot.aot.compilerArguments

Since

excludeGroupIds

Comma separated list of groupId names to exclude (exact match).

Name

excludeGroupIds

Type

java.lang.String

Default value

User property

spring-boot.excludeGroupIds

Since

1.1.0

excludes

Collection of artifact definitions to exclude. The Exclude element defines mandatory groupId and artifactId components and an optional classifier component. When configured as a property, values should be comma-separated with colon-separated components: groupId:artifactId,groupId:artifactId:classifier

Name

excludes

Type

java.util.List

Default value

User property

spring-boot.excludes

Since

1.1.0

generatedClasses

Directory containing the generated classes.

Name

generatedClasses

Type

java.io.File

Default value

${project.build.directory}/spring-aot/main/classes

User property

Since

generatedResources

Directory containing the generated resources.

Name

generatedResources

Type

java.io.File

Default value

${project.build.directory}/spring-aot/main/resources

User property

Since

generatedSources

Directory containing the generated sources.

Name

generatedSources

Type

java.io.File

Default value

${project.build.directory}/spring-aot/main/sources

User property

Since

includes

Collection of artifact definitions to include. The Include element defines mandatory groupId and artifactId components and an optional classifier component. When configured as a property, values should be comma-separated with colon-separated components: groupId:artifactId,groupId:artifactId:classifier

Name

includes

Type

java.util.List

Default value

User property

spring-boot.includes

Since

1.2.0

jvmArguments

JVM arguments that should be associated with the AOT process. On command line, make sure to wrap multiple values between quotes.

Name

jvmArguments

Type

java.lang.String

Default value

User property

spring-boot.aot.jvmArguments

Since

mainClass

Name of the main class to use as the source for the AOT process. If not specified the first compiled class found that contains a 'main' method will be used.

Name

mainClass

Type

java.lang.String

Default value

User property

spring-boot.aot.main-class

Since

profiles

Spring profiles to take into account for AOT processing.

Name

profiles

Type

java.lang.String[]

Default value

User property

Since

skip

Skip the execution.

Name

skip

Type

boolean

Default value

false

User property

spring-boot.aot.skip

Since

systemPropertyVariables

List of JVM system properties to pass to the AOT process.

Name

systemPropertyVariables

Type

java.util.Map

Default value

User property

Since

Processing Tests

The AOT engine can be applied to JUnit 5 tests that use Spring’s Test Context Framework. Suitable tests are processed by the AOT engine in order to generate ApplicationContextInitializer code.

To configure your application to use this feature, add an execution for the process-test-aot goal, as shown in the following example:

<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
	<executions>
		<execution>
			<id>process-test-aot</id>
			<goals>
				<goal>process-test-aot</goal>
			</goals>
		</execution>
	</executions>
</plugin>
If you are using spring-boot-starter-parent, this execution is automatically configured if you enable the nativeTest profile.

As with application AOT processing, the BeanFactory is fully prepared at build-time.

spring-boot:process-test-aot

org.springframework.boot:spring-boot-maven-plugin:3.3.5

Invoke the AOT engine on tests.

Required parameters

Name Type Default

classesDirectory

File

${project.build.outputDirectory}

generatedClasses

File

${project.build.directory}/spring-aot/main/classes

generatedResources

File

${project.build.directory}/spring-aot/test/resources

generatedSources

File

${project.build.directory}/spring-aot/test/sources

generatedTestClasses

File

${project.build.directory}/spring-aot/test/classes

testClassesDirectory

File

${project.build.testOutputDirectory}

Optional parameters

Name Type Default

compilerArguments

String

excludeGroupIds

String

excludes

List

includes

List

jvmArguments

String

skip

boolean

false

systemPropertyVariables

Map

Parameter details

classesDirectory

Directory containing the classes and resource files that should be used to run the tests.

Name

classesDirectory

Type

java.io.File

Default value

${project.build.outputDirectory}

User property

Since

compilerArguments

Arguments that should be provided to the AOT compile process. On command line, make sure to wrap multiple values between quotes.

Name

compilerArguments

Type

java.lang.String

Default value

User property

spring-boot.aot.compilerArguments

Since

excludeGroupIds

Comma separated list of groupId names to exclude (exact match).

Name

excludeGroupIds

Type

java.lang.String

Default value

User property

spring-boot.excludeGroupIds

Since

1.1.0

excludes

Collection of artifact definitions to exclude. The Exclude element defines mandatory groupId and artifactId components and an optional classifier component. When configured as a property, values should be comma-separated with colon-separated components: groupId:artifactId,groupId:artifactId:classifier

Name

excludes

Type

java.util.List

Default value

User property

spring-boot.excludes

Since

1.1.0

generatedClasses

Directory containing the generated test classes.

Name

generatedClasses

Type

java.io.File

Default value

${project.build.directory}/spring-aot/main/classes

User property

Since

generatedResources

Directory containing the generated test resources.

Name

generatedResources

Type

java.io.File

Default value

${project.build.directory}/spring-aot/test/resources

User property

Since

generatedSources

Directory containing the generated sources.

Name

generatedSources

Type

java.io.File

Default value

${project.build.directory}/spring-aot/test/sources

User property

Since

generatedTestClasses

Directory containing the generated test classes.

Name

generatedTestClasses

Type

java.io.File

Default value

${project.build.directory}/spring-aot/test/classes

User property

Since

includes

Collection of artifact definitions to include. The Include element defines mandatory groupId and artifactId components and an optional classifier component. When configured as a property, values should be comma-separated with colon-separated components: groupId:artifactId,groupId:artifactId:classifier

Name

includes

Type

java.util.List

Default value

User property

spring-boot.includes

Since

1.2.0

jvmArguments

JVM arguments that should be associated with the AOT process. On command line, make sure to wrap multiple values between quotes.

Name

jvmArguments

Type

java.lang.String

Default value

User property

spring-boot.aot.jvmArguments

Since

skip

Skip the execution.

Name

skip

Type

boolean

Default value

false

User property

spring-boot.aot.skip

Since

systemPropertyVariables

List of JVM system properties to pass to the AOT process.

Name

systemPropertyVariables

Type

java.util.Map

Default value

User property

Since

testClassesDirectory

Directory containing the classes and resource files that should be packaged into the archive.

Name

testClassesDirectory

Type

java.io.File

Default value

${project.build.testOutputDirectory}

User property

Since