What's New in Project Leyden - JEP 514 and JEP 515 Explained

Wed, 20 Aug 2025 13:26:00 +0000
Java, JVM, Application Performance, Project Leyden

Project Leyden is an ongoing initiative aimed at reducing the startup and warmup time of the Java Virtual Machine. The first completed JEP, identified as JEP 483, was introduced in JDK 24. The upcoming release of JDK 25 will include two additional JEPs:

JEP 514 - Ahead-of-Time Command-Line Ergonomics

JEP 515 - Ahead-of-Time Method Profiling

In this blog post, I would like to describe both of these enhancements.

JEP 514 - Ahead-of-Time Command-Line Ergonomics

At the beginning, a few words of explanation for those who have already read my previous blog post: How to Improve JVM-Based Application Startup Time. I wrote there that to use Project Leyden, all you need to do is just include this single option in your application run command:

-XX:CacheDataStore=myapp.aot

However, this was true only for the early access build of JDK 24 (build 24-leydenpremain+2-8). Starting with the official release of JDK 24, this has changed.

In JDK 24, there is no such flag as CacheDataStore. Instead, we have a few others:

AOTCache

AOTClassLinking

AOTConfiguration

AOTMode

Usage of Project Leyden was split into three parts:

1. Training run of application was necessary to record the AOT configuration:

java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf -jar my-app.jar

2. Then, the created configuration was used for cache creation with such command:

java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:AOTCache=app.aot -jar my-app.jar

3. Finally, we can benefit from the created cache in all subsequent runs:

java -XX:AOTCache=app.aot -jar my-app.jar

JEP 514 has simplified the process. Instead of executing three separate commands, we now only need to run two. The first command handles both recording the AOT configuration and creating the cache. The second command remains unchanged and is used to run the application.

It is possible, since a new command-line option appeared in JDK 25: AOTCacheOutput. When used alone, it effectively splits a single Java launcher invocation into two sub-invocations. The command is structured as follows:

java -XX:AOTCacheOutput=app.aot -jar my-app.jar

There are two separate commands processed under the hood. The first command uses AOTMode=record, which creates the AOT configuration. The second command uses AOTMode=create, which utilizes the configuration generated by the first command to create an AOT cache in a file specified by the AOTCacheOutput option. This process is detailed in the issue related to this JEP:

"It is much easier to explain one command splitting into two sub-commands running under two pre-existing modes, than to explain the interactions of a new combined mode with all other VM features. That is why we choose not to invent a new mode such as record+create."

One of the benefits of this approach is that the AOT configuration file is created automatically and deleted after the cache is generated. In the previous approach, this process had to be done manually. In that case, the name of the AOT configuration file is created by adding the ‘.config’ suffix to the file name specified by the AOTCacheOutput option. For example, if the original file is named app.aot the configuration file will be named app.aot.config.

If someone wants...