Update CDS documentation to cover AOTCache
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run Details
Build and Deploy Snapshot / Trigger Docs Build (push) Blocked by required conditions Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[early-access:true toolchain:true version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[early-access:true toolchain:true version:24], map[id:windows-latest name:Windows]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:windows-latest name:Windows]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:windows-latest name:Windows]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:22], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:22], map[id:windows-latest name:Windows]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:windows-latest name:Windows]) (push) Waiting to run Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Waiting to run Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Waiting to run Details

Closes gh-44970
This commit is contained in:
Moritz Halbritter 2025-04-15 09:50:07 +02:00
parent e5c9aaa269
commit f20e796d2b
4 changed files with 56 additions and 9 deletions

View File

@ -3,7 +3,13 @@
Class Data Sharing (CDS) is a https://docs.oracle.com/en/java/javase/17/vm/class-data-sharing.html[JVM feature] that can help reduce the startup time and memory footprint of Java applications. Class Data Sharing (CDS) is a https://docs.oracle.com/en/java/javase/17/vm/class-data-sharing.html[JVM feature] that can help reduce the startup time and memory footprint of Java applications.
To use it, you should first perform a training run on your application in extracted form: In Java 24, CDS is succeeded by the AOT Cache via https://openjdk.org/jeps/483[JEP 483].
Spring Boot supports both CDS and AOT cache, and it is recommended that you use the latter if it is available in the JVM version you are using (Java 24+).
[[packaging.class-data-sharing.cds]]
== CDS
To use CDS, you should first perform a training run on your application in extracted form:
[source,shell] [source,shell]
---- ----
@ -12,9 +18,9 @@ $ cd application
$ java -XX:ArchiveClassesAtExit=application.jsa -Dspring.context.exit=onRefresh -jar my-app.jar $ java -XX:ArchiveClassesAtExit=application.jsa -Dspring.context.exit=onRefresh -jar my-app.jar
---- ----
This creates an `application.jsa` file that can be reused as long as the application is not updated. This creates an `application.jsa` archive file that can be reused as long as the application is not updated.
To use the cache, you need to add an extra parameter when starting the application: To use the archive file, you need to add an extra parameter when starting the application:
[source,shell] [source,shell]
---- ----
@ -22,3 +28,26 @@ $ java -XX:SharedArchiveFile=application.jsa -jar my-app.jar
---- ----
NOTE: For more details about CDS, refer to the xref:how-to:class-data-sharing.adoc[CDS how-to guide] and the {url-spring-framework-docs}/integration/cds.html[Spring Framework reference documentation]. NOTE: For more details about CDS, refer to the xref:how-to:class-data-sharing.adoc[CDS how-to guide] and the {url-spring-framework-docs}/integration/cds.html[Spring Framework reference documentation].
[[packaging.class-data-sharing.aot-cache]]
== AOT Cache
To use the AOT cache, you should first perform a training run on your application in extracted form:
[source,shell]
----
$ java -Djarmode=tools -jar my-app.jar extract --destination application
$ cd application
$ java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf -Dspring.context.exit=onRefresh -jar my-app.jar
$ java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:AOTCache=app.aot -jar my-app.jar
----
This creates an `app.aot` cache file that can be reused as long as the application is not updated.
The intermediate `app.aotconf` file is no longer needed and can be safely deleted.
To use the cache file, you need to add an extra parameter when starting the application:
[source,shell]
----
$ java -XX:AOTCache=app.aot -jar my-app.jar
----

View File

@ -36,7 +36,7 @@ Here is an example of a `Dockerfile` using `jarmode`.
include::reference:partial$dockerfile[] include::reference:partial$dockerfile[]
# Start the application jar - this is not the uber jar used by the builder # Start the application jar - this is not the uber jar used by the builder
# This jar only contains application code and references to the extracted jar files # This jar only contains application code and references to the extracted jar files
# This layout is efficient to start up and CDS friendly # This layout is efficient to start up and CDS/AOT cache friendly
ENTRYPOINT ["java", "-jar", "application.jar"] ENTRYPOINT ["java", "-jar", "application.jar"]
---- ----
@ -53,14 +53,14 @@ Each of the `COPY` commands relates to the layers extracted by the jarmode.
Of course, a `Dockerfile` can be written without using the `jarmode`. Of course, a `Dockerfile` can be written without using the `jarmode`.
You can use some combination of `unzip` and `mv` to move things to the right layer but `jarmode` simplifies that. You can use some combination of `unzip` and `mv` to move things to the right layer but `jarmode` simplifies that.
Additionally, the layout created by the `jarmode` is CDS friendly out of the box. Additionally, the layout created by the `jarmode` is CDS and AOT cache friendly out of the box.
[[packaging.container-images.dockerfiles.cds]] [[packaging.container-images.dockerfiles.cds]]
== CDS == CDS
If you want to additionally enable xref:reference:packaging/class-data-sharing.adoc[CDS], you can use this `Dockerfile`: If you want to additionally enable xref:reference:packaging/class-data-sharing.adoc#packaging.class-data-sharing.cds[CDS], you can use this `Dockerfile`:
[source,dockerfile] [source,dockerfile]
---- ----
include::reference:partial$dockerfile[] include::reference:partial$dockerfile[]
@ -75,3 +75,21 @@ ENTRYPOINT ["java", "-XX:SharedArchiveFile=application.jsa", "-jar", "applicatio
This is mostly the same as the above `Dockerfile`. This is mostly the same as the above `Dockerfile`.
As the last steps, it creates the CDS archive by doing a training run and passes the CDS parameter to `java -jar`. As the last steps, it creates the CDS archive by doing a training run and passes the CDS parameter to `java -jar`.
[[packaging.container-images.dockerfiles.aot-cache]]
== AOT cache
If you want to additionally enable the xref:reference:packaging/class-data-sharing.adoc#packaging.class-data-sharing.aot-cache[AOT cache], you can use this `Dockerfile`:
[source,dockerfile]
----
include::reference:partial$dockerfile[]
# Execute the AOT cache training run
RUN java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf -Dspring.context.exit=onRefresh -jar application.jar
RUN java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:AOTCache=app.aot -jar application.jar && rm app.aotconf
# Start the application jar with AOT cache enabled - this is not the uber jar used by the builder
# This jar only contains application code and references to the extracted jar files
# This layout is efficient to start up and AOT cache friendly
ENTRYPOINT ["java", "-XX:AOTCache=app.aot", "-jar", "application.jar"]
----
This is mostly the same as the above `Dockerfile`.
As the last steps, it creates the AOT cache file by doing a training run and passes the AOT cache parameter to `java -jar`.

View File

@ -12,7 +12,7 @@ Certain PaaS implementations may also choose to extract archives before they run
For example, Cloud Foundry operates this way. For example, Cloud Foundry operates this way.
Spring Boot supports extracting your application to a directory using different layouts. Spring Boot supports extracting your application to a directory using different layouts.
The default layout is the most efficient, and is xref:reference:packaging/class-data-sharing.adoc[CDS friendly]. The default layout is the most efficient, and it is xref:reference:packaging/class-data-sharing.adoc#packaging.class-data-sharing.cds[CDS] and xref:reference:packaging/class-data-sharing.adoc#packaging.class-data-sharing.aot-cache[AOT cache] friendly.
In this layout, the libraries are extracted to a `lib/` folder, and the application jar In this layout, the libraries are extracted to a `lib/` folder, and the application jar
contains the application classes and a manifest which references the libraries in the `lib/` folder. contains the application classes and a manifest which references the libraries in the `lib/` folder.

View File

@ -1,5 +1,5 @@
# Perform the extraction in a separate builder container # Perform the extraction in a separate builder container
FROM bellsoft/liberica-openjre-debian:17-cds AS builder FROM bellsoft/liberica-openjre-debian:24-cds AS builder
WORKDIR /builder WORKDIR /builder
# This points to the built jar file in the target folder # This points to the built jar file in the target folder
# Adjust this to 'build/libs/*.jar' if you're using Gradle # Adjust this to 'build/libs/*.jar' if you're using Gradle
@ -10,7 +10,7 @@ COPY ${JAR_FILE} application.jar
RUN java -Djarmode=tools -jar application.jar extract --layers --destination extracted RUN java -Djarmode=tools -jar application.jar extract --layers --destination extracted
# This is the runtime container # This is the runtime container
FROM bellsoft/liberica-openjre-debian:17-cds FROM bellsoft/liberica-openjre-debian:24-cds
WORKDIR /application WORKDIR /application
# Copy the extracted jar contents from the builder container into the working directory in the runtime container # Copy the extracted jar contents from the builder container into the working directory in the runtime container
# Every copy step creates a new docker layer # Every copy step creates a new docker layer