Week 151 — How can one use CDS archives to improve startup of Java applications?
Question of the Week #151
How can one use CDS archives to improve startup of Java applications?
2 Replies
CDS allows storing information about parsed classes in a file that can be loaded when starting the application again to improve startup time.
CDS is enabled for JDK classes by default and can be disabled with
-Xshare:off (though that option bringing benefit is pretty rare). To enable it for custom applications, it is possible to create a CDS archive once the application stops using -XX:ArchiveClassesAtExit=myarchive.jsa and use that for improving startup time when running the same application again using -XX:SharedArchiveFile=myarchive.jsa.
Assuming we have a file named myjar.jar, we can run it with java -jar myjar.jar but if we want to make use of (App)CDS, we have to first run it with something like
which runs the application and dumps an archive of the loaded classes.
We can then start it again to make sure it uses the created archive:
For simple applications like a "Hello World", this is unlikely to bring much benefit but for applications loading a lot of classes, this can result in significant improvements in startup time.
As running the application twice with different arguments can be a problem, it is possible to use the -XX:+AutoCreateSharedArchive option which will automatically create the CDS archive once the application completes if it is not present and use it when it's started with the same command:
While CDS can improve startup time, it is possible to do more since JDK 24 using AOT caches. These can not just store parsed classes but directly store classes in their loaded and linked state. With JDK 25, these AOT caches can also include profiling data from the JIT.
Since JDK 24, creating an AOT archive requires 3 steps. First, a training run can be executed with -XX:AOTMode=record and -XX:AOTConfiguration=myapp.aotconf which stores information about the classes in a file named app.aotconf
Then, this AOT configuration file can be "assembled" into an AOT cache (in this case myapp.aot with the following command:
Once the AOT cache is created, the application can be run with just the -XX:AOTCache=myapp.aot option to benefit from the improved startup time:
In JDK 25, this process was made easier by allowing users to skip the assembly phase. To create an AOT cache, the application just needs to be run with -XX:AOTCacheOutput=myapp.aot:
Once that is done, it can benefit from the improved startup time using the same command as before:
In future JDK releases, the AOT cache may be expanded to include more information and improve startup time even more.
One thing to note AOT caches have some requirements that may not be immediately obvious (e.g. the same JVM should be using for the training and testing runs)To see an example of the benefits one can achieve with CDS or AOT caches, I ran a Spring application (which is used in production) in different ways (using Spring's support for extracted JAR files which can be achieved using
java -Djarmode=tools -jar myspringapp.jar extract). When starting it without CDS or the AOT cache, it typically takes between 9-10 seconds to start.
When running it with with CDS, that reduced the startup time of that application to around 6-8 seconds.
With the AOT cache, starting that application typically takes around 5-6 seconds on JDK 25 but only arund 3-4 seconds using the latest early-access Leyden build from https://jdk.java.net/leyden/ at the time of writing (Build 26-leydenpremain+1).
📖 Sample answer from dan1st