Skip to content

Commit fb736e8

Browse files
philwebbmhalbritter
andcommitted
Add native image reference documentation
Update reference documentation with a new "native image" section. This commit includes some work derived from the "Spring Native" project documentation written by Andy Clement, Sébastien Deleuze, Filip Hanik, Dave Syer, Esteban Ginez, Jay Bryant, Brian Clozel, Stéphane Nicoll, and Josh Long. Closes gh-32582 Co-authored-by: Moritz Halbritter <[email protected]>
1 parent 0219b22 commit fb736e8

File tree

24 files changed

+1070
-1
lines changed

24 files changed

+1070
-1
lines changed

spring-boot-project/spring-boot-docs/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ tasks.withType(org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask) {
317317
"spring-integration-version": versionConstraints["org.springframework.integration:spring-integration-core"],
318318
"spring-kafka-version": versionConstraints["org.springframework.kafka:spring-kafka"],
319319
"spring-security-version": securityVersion,
320+
"native-build-tools-version": nativeBuildToolsVersion,
320321
"spring-webservices-version": versionConstraints["org.springframework.ws:spring-ws-core"],
321322
"remote-spring-application-output": runRemoteSpringApplicationExample.outputs.files.singleFile,
322323
"spring-application-output": runSpringApplicationExample.outputs.files.singleFile,

spring-boot-project/spring-boot-docs/src/docs/asciidoc/attributes.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,6 @@
110110
:micrometer-concepts-docs: {micrometer-docs}/concepts
111111
:micrometer-registry-docs: {micrometer-docs}/registry
112112
:tomcat-docs: https://tomcat.apache.org/tomcat-9.0-doc
113+
:graal-version: 22.2
114+
:graal-native-image-docs: https://www.graalvm.org/{graal-version}/reference-manual/native-image
115+
:liberica-nik-download: https://bell-sw.com/pages/downloads/native-image-kit/

spring-boot-project/spring-boot-docs/src/docs/asciidoc/deployment/whats-next.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ See the https://www.cloudfoundry.org/[Cloud Foundry], https://www.heroku.com/[He
44
These are just four of the most popular Java PaaS providers.
55
Since Spring Boot is so amenable to cloud-based deployment, you can freely consider other providers as well.
66

7-
The next section goes on to cover the _<<cli#cli, Spring Boot CLI>>_, or you can jump ahead to read about _<<build-tool-plugins#build-tool-plugins, build tool plugins>>_.
7+
The next section goes on to cover the _<<native-image#native-image, GraalVM Native Images>>_, or you can jump ahead to read about the _<<cli#cli, Spring Boot CLI>>_ or our _<<build-tool-plugins#build-tool-plugins, build tool plugins>>_.

spring-boot-project/spring-boot-docs/src/docs/asciidoc/documentation.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,6 @@ include::documentation/io.adoc[]
3232

3333
include::documentation/container-images.adoc[]
3434

35+
include::documentation/native-images.adoc[]
36+
3537
include::documentation/advanced.adoc[]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[[documentation.native-images]]
2+
== GraalVM Native Images
3+
Spring Boot applications can be converted into native executables using GraalVM.
4+
You can read more about our native image support here:
5+
6+
* *GraalVM Native Images:* <<native-image#native-image.introducing-graalvm-native-images, Introduction>> | <<native-image#native-image.introducing-graalvm-native-images.key-differences-with-jvm-deployments, Key Differences with the JVM>> | <<native-image#native-image.introducing-graalvm-native-images.understanding-aot-processing, Ahead-of-Time Processing>>
7+
* *Getting Started:* <<native-image#native-image.developing-your-first-application.buildpacks, Buildpacks>> | <<native-image#native-image.developing-your-first-application.native-build-tools, Native Build Tools>>
8+
* *Testing:* <<native-image#native-image.testing.with-the-jvm, JVM>> | <<native-image#native-image.testing.with-native-build-tools, Native Build Tools>>
9+
* *Advanced Topics:* <<native-image#native-image.advanced.nested-configuration-properties, Nested Configuration Properties>> | <<native-image#native-image.advanced.converting-executable-jars, Converting JARs>> | <<native-image#native-image.advanced.known-limitations, Known Limitations>>

spring-boot-project/spring-boot-docs/src/docs/asciidoc/getting-started/system-requirements.adoc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,24 @@ Spring Boot supports the following embedded servlet containers:
3535
|===
3636

3737
You can also deploy Spring Boot applications to any servlet 5.0+ compatible container.
38+
39+
40+
41+
[[getting-started.system-requirements.graal]]
42+
=== GraalVM Native Images
43+
Spring Boot applications can be <<native-image#native-image.introducing-graalvm-native-images,converted into a Native Image>> using using Graal {graal-version} or above.
44+
45+
Images can be created using the https://github.com/graalvm/native-build-tools[native build tools] Gradle/Maven plugins or `native-image` tool provided by GraalVM.
46+
You can also create native images using the the https://github.com/paketo-buildpacks/native-image[native-image Paketo buildpack].
47+
48+
The following versions are supported:
49+
50+
|===
51+
| Name | Version
52+
53+
| GraalVM Community
54+
| {graal-version}
55+
56+
| Native Build Tools
57+
| {native-build-tools-version}
58+
|===

spring-boot-project/spring-boot-docs/src/docs/asciidoc/index.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ The reference documentation consists of the following sections:
2323
<<container-images#container-images,Container Images>> :: Efficient container images and Building container images with Dockerfiles and Cloud Native Buildpacks.
2424
<<actuator#actuator,Production-ready Features>> :: Monitoring, Metrics, Auditing, and more.
2525
<<deployment#deployment,Deploying Spring Boot Applications>> :: Deploying to the Cloud, and Installing as a Unix application.
26+
<<native-image#native-image,Graal Native Image Support>> :: Create a native executable from your application using GraalVM
2627
<<cli#cli,Spring Boot CLI>> :: Installing the CLI, Using the CLI, Configuring the CLI, and more.
2728
<<build-tool-plugins#build-tool-plugins,Build Tool Plugins>> :: Maven Plugin, Gradle Plugin, Antlib, and more.
2829
<<howto#howto,"`How-to`" Guides>> :: Application Development, Configuration, Embedded Servers, Data Access, and many more.

spring-boot-project/spring-boot-docs/src/docs/asciidoc/index.singleadoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ include::actuator.adoc[leveloffset=+1]
3939

4040
include::deployment.adoc[leveloffset=+1]
4141

42+
include::native-image.adoc[leveloffset=+1]
43+
4244
include::cli.adoc[leveloffset=+1]
4345

4446
include::build-tool-plugins.adoc[leveloffset=+1]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[[native-image]]
2+
= GraalVM Native Image Support
3+
include::attributes.adoc[]
4+
5+
https://www.graalvm.org/native-image/[GraalVM Native Images] are standalone executables that can be generated by processing compiled Java applications ahead-of-time.
6+
Native Images generally have a smaller memory footprint and start faster than their JVM counterparts.
7+
8+
include::native-image/introducing-graalvm-native-images.adoc[]
9+
10+
include::native-image/developing-your-first-application.adoc[]
11+
12+
include::native-image/testing-native-applications.adoc[]
13+
14+
include::native-image/advanced-topics.adoc[]
15+
16+
include::native-image/whats-next.adoc[]
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
[[native-image.advanced]]
2+
== Advanced Native Images Topics
3+
4+
5+
6+
[[native-image.advanced.nested-configuration-properties]]
7+
=== Nested Configuration Properties
8+
Reflection hints are automatically created for configuration properties by Spring's ahead-of-time engine.
9+
Nested configuration properties, however, *must* be annotated with `@NestedConfigurationProperty`, otherwise they won't be detected and will not be bindable.
10+
11+
include::code:MyProperties[]
12+
13+
The example above produces configuration properties for `my.properties.name` and `my.properties.nested.number`.
14+
Without the `@NestedConfigurationProperty` annotation on the `nested` field, the `my.properties.nested.number` property would not be bindable in a native image.
15+
16+
NOTE: Please use public getters / setters, otherwise the properties won't be bindable.
17+
18+
19+
20+
[[native-image.advanced.converting-executable-jars]]
21+
=== Converting a Spring Boot Executable JAR
22+
It is possible to convert a Spring Boot <<executable-jar#appendix.executable-jar, executable JAR>> into a native image as long at the jar contains the AOT generated assets.
23+
This can be useful for a number of reasons, including:
24+
25+
* You can keeping your regular JVM pipeline and turn the JVM application into a native image on your CI/CD platform.
26+
* As `native-image` https://github.com/oracle/graal/issues/407[does not support cross-compilation], you can keep an OS neutral deployment artifact which you convert later to different OS architectures.
27+
28+
You can convert a Spring Boot executable jar into a native image using buildpacks, or the `native-image` tool that is shipped with GraalVM.
29+
30+
NOTE: Your executable JAR must include AOT generated assets such as generated classes and JSON hint files.
31+
32+
33+
34+
[[native-image.advanced.converting-executable-jars.buildpacks]]
35+
==== Using Buildpacks
36+
Spring Boot applications usually use Buildpacks via the Maven (`mvn spring-boot:build-image`), or Gradle (`gradle bootBuildImage`) integrations.
37+
You can, however, also use https://buildpacks.io//docs/tools/pack/[`pack`] to turn an AOT processed Spring Boot executable JAR into a native container image.
38+
39+
40+
First, make sure that a Docker daemon is available (see https://docs.docker.com/installation/#installation[Get Docker] for more details).
41+
https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user[Configure it to allow non-root user] if you are on Linux.
42+
43+
You also need to install `pack` by following https://buildpacks.io//docs/tools/pack/#install[the installation guide on buildpacks.io].
44+
45+
Assuming an AOT processed Spring Boot executable JAR built as `myproject-0.0.1-SNAPSHOT.jar` is in the `target` directory, run:
46+
47+
[source,shell,indent=0,subs="verbatim"]
48+
----
49+
$ pack build --builder paketobuildpacks/builder:tiny \
50+
--path target/myproject-0.0.1-SNAPSHOT.jar \
51+
--env 'BP_NATIVE_IMAGE=true' \
52+
my-application:0.0.1-SNAPSHOT
53+
----
54+
55+
NOTE: You do not need to have a local GraalVM installation to generate an image in this way.
56+
57+
Once `pack` has finished, you can launch the application using `docker run`:
58+
59+
[source,shell,indent=0,subs="verbatim"]
60+
----
61+
$ docker run --rm -p 8080:8080 docker.io/library/myproject:0.0.1-SNAPSHOT
62+
----
63+
64+
65+
66+
[[native-image.advanced.converting-executable-jars.native-image]]
67+
==== Using GraalVM native-image
68+
Another option to turn an AOT processed Spring Boot executable JAR into a native executable is to use the GraalVM `native-image` tool.
69+
For this to work, you'll need a GraalVM distribution on your machine.
70+
You can either download it manually on the {liberica-nik-download}[Liberica Native Image Kit page] or you can use a download manager like SDKMAN!.
71+
72+
Assuming an AOT processed Spring Boot executable JAR built as `myproject-0.0.1-SNAPSHOT.jar` is in the `target` directory, run:
73+
74+
[source,shell,indent=0,subs="verbatim"]
75+
----
76+
$ rm -rf target/native
77+
$ mkdir -p target/native
78+
$ cd target/native
79+
$ jar -xvf ../myproject-0.0.1-SNAPSHOT.jar
80+
$ native-image -H:Name=myproject @META-INF/native-image/argfile -cp .:BOOT-INF/classes:`find BOOT-INF/lib | tr '\n' ':'`
81+
$ mv myproject ../
82+
----
83+
84+
NOTE: These commands work on Linux or MacOS machines, you will need to adapt them for Windows.
85+
86+
TIP: The `@META-INF/native-image/argfile` might not be packaged in your jar.
87+
It is only included when reachability metadata overrides are needed.
88+
89+
WARNING: The `native-image` `-cp` flag does not not accept wildcards.
90+
You need to ensure that all jars are listed (the command above uses `find` and `tr` to do this).
91+
92+
93+
94+
[[native-image.advanced.using-the-tracing-agent]]
95+
=== Using the Tracing Agent
96+
The GraalVM native image https://www.graalvm.org/reference-manual/native-image/Agent/[tracing agent] allows you to intercept reflection, resources or proxy usage on the JVM in order to generate the related hints.
97+
Spring should generate most of these hints automatically, but the tracing agent can be used to quickly identify the missing entries.
98+
99+
When using the agent to generate hints for a native image, there are a couple of approaches:
100+
101+
* Launch the application directly and exercise it.
102+
* Run application tests to exercise the application.
103+
104+
The first option is interesting for identifying the missing hints when a library or a pattern is not recognized by Spring.
105+
106+
The second option sounds more appealing for a repeatable setup, but by default the generated hints will include anything required by the test infrastructure.
107+
Some of these will be unnecessary when the application runs for real.
108+
To address this problem the agent supports an access-filter file that will cause certain data to be excluded from the generated output.
109+
110+
111+
112+
[[native-image.advanced.using-the-tracing-agent.launch]]
113+
==== Launch the Application Directly
114+
Use the following command to launch the application with the native image tracing agent attached:
115+
116+
[source,shell,indent=0,subs="verbatim,attributes"]
117+
----
118+
$ java -Dspring.aot.enabled=true \
119+
-agentlib:native-image-agent=config-output-dir=/path/to/config-dir/ \
120+
-jar target/myproject-0.0.1-SNAPSHOT.jar
121+
----
122+
123+
Now you can exercise the code paths you want to have hints for and then stop the application with `ctrl-c`.
124+
125+
On application shutdown the native image tracing agent will write the hint files to the given config output directory.
126+
You can either manually inspect these files, or use them as input to the native image build process.
127+
To use them as input, copy them into the `src/main/resources/META-INF/native-image/` directory.
128+
The next time you build the native image, GraalVM will take these files into consideration.
129+
130+
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.
131+
For further reading, please see https://www.graalvm.org/reference-manual/native-image/Agent/[the official documentation].
132+
133+
134+
135+
[[native-image.advanced.custom-hints]]
136+
=== Custom Hints
137+
If you need to provide your own hints for reflection, resources, serialization, proxy usage etc. you can use the `RuntimeHintsRegistrar` API.
138+
Create a class that implements the `RuntimeHintsRegistrar` interface, then make appropriate calls to the provided `RuntimeHints` instance:
139+
140+
include::code:MyRuntimeHints[]
141+
142+
You can then use `@ImportRuntimeHints` on any `@Configuration` class (for example your `@SpringBootApplication` annotated application class) to activate those hints.
143+
144+
145+
146+
[[native-image.advanced.custom-hints.testing]]
147+
==== Testing custom hints
148+
The `RuntimeHintsPredicates` API can be used to test your hints.
149+
The API provides methods that build a `Predicate` that can be used to test a `RuntimeHints` instance.
150+
151+
If you're using AssertJ, your test would look like this:
152+
153+
include::code:MyRuntimeHintsTests[]
154+
155+
156+
157+
[[native-image.advanced.known-limitations]]
158+
=== Known Limitations
159+
GraalVM native images are an evolving technology and not all libraries provide support.
160+
The GraalVM community is helping by providing https://github.com/oracle/graalvm-reachability-metadata[reachability metadata] for projects that don't yet ship their own.
161+
Spring itself doesn't contain hints for 3rd party libraries and instead relies on the reachability metadata project.
162+
163+
If you encounter problems when generating native images for Spring Boot applications, please check the {github-wiki}/Known-GraalVM-Native-Image-Limitations[Known GraalVM Native Image Limitations] page of the Spring Boot wiki.
164+
You can also contribute issues to the https://github.com/spring-projects/spring-aot-smoke-tests[spring-aot-smoke-tests] project on GitHub which is used to confirm that common application types are working as expected.
165+
166+
If you find a library which doesn't work with GraalVM, please raise an issue on the https://github.com/oracle/graalvm-reachability-metadata[reachability metadata project].

0 commit comments

Comments
 (0)