Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreHow can Spring Boot developers improve the runtime efficiency of their applications with minimal constraints in order to enjoy those benefits on most applications? The answer is the CDS support introduced by Spring Boot 3.3 which allows you to start your Spring Boot applications faster and consume less memory. It is based on the foundation introduced by Spring Framework 6.1 that I presented a few months ago.
A key point is that this new CDS support provides a different value proposition compared to the GraalVM native image support: the improvements you get with CDS are less dramatic than with native images on startup time for example, but they are still very significant while you can continue to use your regular JVM with very few side effects.
Spring Boot supports both CDS and GraalVM native images in a production-ready fashion and gives you the choice depending on your context and opinions.
CDS stands for Class Data Sharing, it is a mature technology already available and used in most JVM, but so far not at its full potential. To simplify, you are probably already using CDS without knowing it but only for optimizing JDK classes loading, while the classes of your application or libraries probably do not take advantage of it. To unlock that, it is required to perform a training run of your application.
You also need to fulfill a set of constraints that are easy to break without a dedicated support like Spring Boot one:
*
wildcard characters and nested JARs.Spring Boot 3.3 unlocks this potential by providing 2 new features: self-extracting executable JAR and Buildpacks CDS support.
Directly running java -jar my-app.jar
with the executable JAR is not the most efficient way to run your application on production. This is documented but most developers and operators not using Buildpacks miss that based on various discussions I had with the Spring community. And until recently, there was no real first-class feature to help.
Spring Boot 3.3 changes that and introduces the capability for an executable JAR to self-extract without requiring any external tool, just with the java command likely already available to run the application:
java -Djarmode=tools -jar my-app.jar extract --destination application
You can then run your Spring Boot application more efficiently with:
java -jar application/my-app.jar
This feature has a superpower: it has been designed to fulfill CDS (and Project Leyden) constraints. So combined with Spring Framework support for CDS training runs, you can create a CDS archive for your Spring Boot application as following:
java -XX:ArchiveClassesAtExit=application.jsa -Dspring.context.exit=onRefresh -jar application/my-app.jar
Then you can start your application with CDS enabled with:
java -XX:SharedArchiveFile=application.jsa -jar application/my-app.jar
The self-extracting executable JAR feature combined with CDS usage is flexible but still requires quite a lot of manual steps, so Spring Boot and Buildpacks provide integrated support for CDS which:
As demonstrated in the https://github.com/sdeleuze/spring-boot-cds-demo repository, it can be enabled as following with Gradle:
tasks.named("bootBuildImage") {
environment["BP_JVM_CDS_ENABLED"] = "true"
}
Or with Maven:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<env>
<BP_JVM_CDS_ENABLED>true</BP_JVM_CDS_ENABLED>
</env>
</image>
</configuration>
</plugin>
During the training run, the Spring beans are instantiated without starting the Spring lifecycle, so in practice the main side effect you may observe is early database interactions which can be avoided by configuring your application (or just the training run with the CDS_TRAINING_JAVA_TOOL_OPTIONS
environment variable) to prevent such database interaction as documented here.
It is also possible to trigger Spring AOT activation support with the BP_SPRING_AOT_ENABLED
environment variable but make sure to have those constraints in mind:
CDS_TRAINING_JAVA_TOOL_OPTIONS
and BP_SPRING_AOT_ENABLED
can’t be combined.The Spring and Buildpacks teams at Broadcom have been collaborating closely to leverage those OSS features and combine them with additional Tanzu Platform capabilities in order to provide a first-class CDS support for Cloud Foundry or Kubernetes, allowing for example training run autoconfiguration, making CDS as easy to enable as a flag with no side effects, and more platform-level capabilities are coming.
With a minimal Spring MVC Tomcat application running on a MacBook M2, we observe that the extracted application combined with CDS allows approximately 1.5x faster startup and 16% lower memory consumption compared to running the executable JAR. If we add Spring AOT to the mix, we get approximately 2x faster startup and 27% lower memory consumption.
We see similar improvements for Petclinic.
The values will obviously change on less powerful cloud instances, but you should likely observe similar improvement ratios.
Interestingly, the CDS friendly layout used by the new extract command described above is also designed to provide optimal performance with Project Leyden Early-Access builds which can be seen as a CDS successor with additional capabilities allowing:
We observe for now approximately 3x faster startup on Spring Boot applications with Project Leyden and 4x faster startup when combining Project Leyden and Spring AOT.
I will share more in the upcoming Project Leyden talk at Devoxx Belgium 2024 that I will have the pleasure to co-present with Per Minborg from the Java Platform team.