Move JAR unpacking section and add AOT on JVM section

Closes gh-32905
This commit is contained in:
Moritz Halbritter 2023-05-03 16:01:19 +02:00
parent bdca30e85b
commit 46fedfc4ef
4 changed files with 84 additions and 29 deletions

View File

@ -1,3 +1,19 @@
#
# Copyright 2012-2023 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Spring Boot 2.x - 2.4 Migrations
#---------------------------------------------------
spring-boot-reference-documentation=index
@ -1017,3 +1033,6 @@ actuator.tracing.custom=actuator.http-exchanges.custom
# Spring Boot 3.0 - 3.1 migrations
howto.testing.testcontainers=features.testing.testcontainers
howto.testing.testcontainers.dynamic-properties=features.testing.testcontainers.dynamic-properties
# gh-32905
container-images.efficient-images.unpacking=deployment.efficient.unpacking

View File

@ -8,35 +8,6 @@ Since you probably recompile your code more often than you upgrade the version o
If you put jar files in the layer before your application classes, Docker often only needs to change the very bottom layer and can pick others up from its cache.
[[container-images.efficient-images.unpacking]]
=== Unpacking the Executable JAR
If you are running your application from a container, you can use an executable jar, but it is also often an advantage to explode it and run it in a different way.
Certain PaaS implementations may also choose to unpack archives before they run.
For example, Cloud Foundry operates this way.
One way to run an unpacked archive is by starting the appropriate launcher, as follows:
[source,shell,indent=0,subs="verbatim"]
----
$ jar -xf myapp.jar
$ java org.springframework.boot.loader.JarLauncher
----
This is actually slightly faster on startup (depending on the size of the jar) than running from an unexploded archive.
After startup you should not expect any differences.
Once you have unpacked the jar file, you can also get an extra boost to startup time by running the app with its "natural" main method instead of the `JarLauncher`. For example:
[source,shell,indent=0,subs="verbatim"]
----
$ jar -xf myapp.jar
$ java -cp BOOT-INF/classes:BOOT-INF/lib/* com.example.MyApplication
----
NOTE: Using the `JarLauncher` over the application's main method has the added benefit of a predictable classpath order.
The jar contains a `classpath.idx` file which is used by the `JarLauncher` when constructing the classpath.
[[container-images.efficient-images.layering]]
=== Layering Docker Images
To make it easier to create optimized Docker images, Spring Boot supports adding a layer index file to the jar.

View File

@ -14,4 +14,6 @@ include::deployment/cloud.adoc[]
include::deployment/installing.adoc[]
include::deployment/efficient.adoc[]
include::deployment/whats-next.adoc[]

View File

@ -0,0 +1,63 @@
[[deployment.efficient]]
== Efficient deployments
[[deployment.efficient.unpacking]]
=== Unpacking the Executable JAR
If you are running your application from a container, you can use an executable jar, but it is also often an advantage to explode it and run it in a different way.
Certain PaaS implementations may also choose to unpack archives before they run.
For example, Cloud Foundry operates this way.
One way to run an unpacked archive is by starting the appropriate launcher, as follows:
[source,shell,indent=0,subs="verbatim"]
----
$ jar -xf myapp.jar
$ java org.springframework.boot.loader.JarLauncher
----
This is actually slightly faster on startup (depending on the size of the jar) than running from an unexploded archive.
After startup, you should not expect any differences.
Once you have unpacked the jar file, you can also get an extra boost to startup time by running the app with its "natural" main method instead of the `JarLauncher`. For example:
[source,shell,indent=0,subs="verbatim"]
----
$ jar -xf myapp.jar
$ java -cp "BOOT-INF/classes:BOOT-INF/lib/*" com.example.MyApplication
----
NOTE: Using the `JarLauncher` over the application's main method has the added benefit of a predictable classpath order.
The jar contains a `classpath.idx` file which is used by the `JarLauncher` when constructing the classpath.
[[deployment.efficient.aot]]
=== Using Ahead-of-time Processing With the JVM
It's beneficial for the startup time to run your application using the AOT generated initialization code.
First, you need to ensure that the jar you are building includes AOT generated code.
For Maven, this means that you should build with `-Pnative` to activate the `native` profile:
[source,shell,indent=0,subs="verbatim"]
----
$ mvn -Pnative package
----
For Gradle, you need to ensure that your build includes the `org.springframework.boot.aot` plugin.
When the JAR has been built, run it with `spring.aot.enabled` system property set to `true`. For example:
[source,shell,indent=0,subs="verbatim"]
----
$ java -Dspring.aot.enabled=true -jar myapplication.jar
........ Starting AOT-processed MyApplication ...
----
Beware that using the ahead-of-time processing has drawbacks.
It implies the following restrictions:
* The classpath is fixed and fully defined at build time
* The beans defined in your application cannot change at runtime, meaning:
- The Spring `@Profile` annotation and profile-specific configuration is not supported
- Properties that change if a bean is created are not supported (for example, `@ConditionalOnProperty` and `.enable` properties).
To learn more about ahead-of-time processing, please see the <<native-image#native-image.introducing-graalvm-native-images.understanding-aot-processing,Understanding Spring Ahead-of-Time Processing section>>.