From f20e796d2b03e644c3cd1fd08a8fd33a9e4d55eb Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 15 Apr 2025 09:50:07 +0200 Subject: [PATCH] Update CDS documentation to cover AOTCache Closes gh-44970 --- .../pages/packaging/class-data-sharing.adoc | 35 +++++++++++++++++-- .../container-images/dockerfiles.adoc | 24 +++++++++++-- .../reference/pages/packaging/efficient.adoc | 2 +- .../modules/reference/partials/dockerfile | 4 +-- 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/class-data-sharing.adoc b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/class-data-sharing.adoc index 12e9cf6901e..288a60b5002 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/class-data-sharing.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/class-data-sharing.adoc @@ -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. -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] ---- @@ -12,9 +18,9 @@ $ cd application $ 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] ---- @@ -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]. + +[[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 +---- diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/container-images/dockerfiles.adoc b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/container-images/dockerfiles.adoc index 69be0b37aef..0e43466a171 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/container-images/dockerfiles.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/container-images/dockerfiles.adoc @@ -36,7 +36,7 @@ Here is an example of a `Dockerfile` using `jarmode`. include::reference:partial$dockerfile[] # 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 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"] ---- @@ -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`. 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]] == 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] ---- 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`. 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`. diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/efficient.adoc b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/efficient.adoc index 7cf034b685d..382601fdd4e 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/efficient.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/packaging/efficient.adoc @@ -12,7 +12,7 @@ Certain PaaS implementations may also choose to extract archives before they run For example, Cloud Foundry operates this way. 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 contains the application classes and a manifest which references the libraries in the `lib/` folder. diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/partials/dockerfile b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/partials/dockerfile index 8985fde04be..8acc7aa9b69 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/partials/dockerfile +++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/partials/dockerfile @@ -1,5 +1,5 @@ # 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 # This points to the built jar file in the target folder # 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 # This is the runtime container -FROM bellsoft/liberica-openjre-debian:17-cds +FROM bellsoft/liberica-openjre-debian:24-cds WORKDIR /application # 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