169 lines
9.1 KiB
Plaintext
169 lines
9.1 KiB
Plaintext
[[native-image.advanced]]
|
|
== Advanced Native Images Topics
|
|
|
|
|
|
|
|
[[native-image.advanced.nested-configuration-properties]]
|
|
=== Nested Configuration Properties
|
|
Reflection hints are automatically created for configuration properties by the Spring ahead-of-time engine.
|
|
Nested configuration properties which are no inner classes, however, *must* be annotated with `@NestedConfigurationProperty`, otherwise they won't be detected and will not be bindable.
|
|
|
|
include::code:MyProperties[]
|
|
|
|
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.
|
|
|
|
NOTE: Please use public getters and setters, otherwise the properties will not be bindable.
|
|
|
|
|
|
|
|
[[native-image.advanced.converting-executable-jars]]
|
|
=== Converting a Spring Boot Executable Jar
|
|
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.
|
|
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` 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.
|
|
|
|
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.
|
|
|
|
NOTE: Your executable jar must include AOT generated assets such as generated classes and JSON hint files.
|
|
|
|
|
|
|
|
[[native-image.advanced.converting-executable-jars.buildpacks]]
|
|
==== Using Buildpacks
|
|
Spring Boot applications usually use Cloud Native Buildpacks via the Maven (`mvn spring-boot:build-image`), or Gradle (`gradle bootBuildImage`) integrations.
|
|
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.
|
|
|
|
|
|
First, make sure that a Docker daemon is available (see https://docs.docker.com/installation/#installation[Get Docker] for more details).
|
|
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.
|
|
|
|
You also need to install `pack` by following https://buildpacks.io//docs/tools/pack/#install[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:
|
|
|
|
[source,shell,indent=0,subs="verbatim"]
|
|
----
|
|
$ pack build --builder paketobuildpacks/builder:tiny \
|
|
--path target/myproject-0.0.1-SNAPSHOT.jar \
|
|
--env 'BP_NATIVE_IMAGE=true' \
|
|
my-application:0.0.1-SNAPSHOT
|
|
----
|
|
|
|
NOTE: 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`:
|
|
|
|
[source,shell,indent=0,subs="verbatim"]
|
|
----
|
|
$ docker run --rm -p 8080:8080 docker.io/library/myproject:0.0.1-SNAPSHOT
|
|
----
|
|
|
|
|
|
|
|
[[native-image.advanced.converting-executable-jars.native-image]]
|
|
==== 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-nik-download}[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:
|
|
|
|
[source,shell,indent=0,subs="verbatim"]
|
|
----
|
|
$ 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 ../
|
|
----
|
|
|
|
NOTE: These commands work on Linux or MacOS machines, you will need to adapt them for Windows.
|
|
|
|
TIP: The `@META-INF/native-image/argfile` might not be packaged in your jar.
|
|
It is only included when reachability metadata overrides are needed.
|
|
|
|
WARNING: 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).
|
|
|
|
|
|
|
|
[[native-image.advanced.using-the-tracing-agent]]
|
|
=== Using the Tracing Agent
|
|
The GraalVM native image {graal-native-image-docs}/metadata/AutomaticMetadataCollection[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.
|
|
|
|
|
|
|
|
[[native-image.advanced.using-the-tracing-agent.launch]]
|
|
==== Launch the Application Directly
|
|
Use the following command to launch the application with the native image tracing agent attached:
|
|
|
|
[source,shell,indent=0,subs="verbatim,attributes"]
|
|
----
|
|
$ 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 {graal-native-image-docs}/metadata/AutomaticMetadataCollection[the official documentation].
|
|
|
|
|
|
|
|
[[native-image.advanced.custom-hints]]
|
|
=== Custom Hints
|
|
If you need to provide your own hints for reflection, resources, serialization, proxy usage etc. you can use the `RuntimeHintsRegistrar` API.
|
|
Create a class that implements the `RuntimeHintsRegistrar` interface, then make appropriate calls to the provided `RuntimeHints` instance:
|
|
|
|
include::code:MyRuntimeHints[]
|
|
|
|
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 needs binding (mostly needed when serializing or deserializing JSON), you can use {spring-framework-docs}/core.html#aot-hints-register-reflection-for-binding[`@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` or `RestTemplate` directly, you might need to use `RegisterReflectionForBinding`.
|
|
|
|
[[native-image.advanced.custom-hints.testing]]
|
|
==== 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:
|
|
|
|
include::code:MyRuntimeHintsTests[]
|
|
|
|
|
|
|
|
[[native-image.advanced.known-limitations]]
|
|
=== Known Limitations
|
|
GraalVM native images are an evolving technology and not all libraries provide support.
|
|
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.
|
|
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 {github-wiki}/Known-GraalVM-Native-Image-Limitations[Known GraalVM Native Image Limitations] page of the Spring Boot wiki.
|
|
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.
|
|
|
|
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].
|