Core Java

Project Leyden: Faster Java Startup Without GraalVM’s Pain, and What You Give Up

Java startup has long been the price of a smart runtime. GraalVM Native Image fixed it by replacing the JVM, but that fix came with strings attached. Project Leyden takes a gentler road. So what exactly do you win, and what do you quietly lose?

First, a Timeline Check

Before we compare anything, let’s get the dates straight, because they are easy to mix up. Project Leyden has been shipping in small pieces. Method profiling (JEP 515) arrived in JDK 25, which is a long-term support release. However, the headline feature, full ahead-of-time code compilation, did not make JDK 26 or JDK 27.

In fact, JDK 27 reached general availability on September 15, 2026 without it. Instead, JEP 544 lists JDK 28 as its release, with a status of “Proposed to Target”. That means it is promising, but it is not final yet.

JEPWhat it doesJDKStatus
483Caches loaded and linked classes24Delivered
514One-command cache creation25 (LTS)Delivered
515Caches method profiles for faster warmup25 (LTS)Delivered
516Cache works with any garbage collector, including ZGC26Delivered
544Caches compiled native code28 (proposed)Proposed to Target

Sources: the JEP pages themselves, plus the BackendBytes JEP-to-JDK mapping, which was checked against the OpenJDK pages in September 2026.

Where GraalVM’s Pain Comes From

GraalVM Native Image compiles your app into a standalone executable. As a result, it starts in milliseconds and uses little memory. Yet it relies on a “closed-world” rule: everything must be known at build time.

That rule creates real work. According to the GraalVM metadata docs, Java cannot load new classes at run time in a native image, and dynamic features such as reflection need extra metadata. Moreover, the build itself is heavy, so teams usually keep a normal JVM build for daily development. None of this is a flaw. It is simply the cost of removing the JVM.

How Leyden Takes a Different Road

Leyden keeps the JVM. Instead, it moves work earlier in time. You run your app once in a “training run”, and the JVM saves what it learned into an AOT cache file. Later, production runs load that cache and skip much of the startup work.

Because it is still HotSpot underneath, reflection, dynamic class loading and your usual tools keep working. Furthermore, if the cache does not fit, the JVM falls back to its normal interpreter and JIT. Therefore, the worst case is an ordinary start, not a crash.

Try It Yourself

The workflow needs JDK 25 or newer. I tested these two commands on Temurin 25.0.4.1 with a tiny stream-based program packed into app.jar. The first command trains and builds the cache, and the second one uses it.

java -XX:AOTCacheOutput=app.aot -cp app.jar HelloStream
java -XX:AOTCache=app.aot -cp app.jar HelloStream

Both commands printed the expected output. Keep one detail in mind: the one-step command runs a second JVM to assemble the cache. BackendBytes notes, citing JEP 514, that this assembly step uses its own heap of the same size, so memory-limited CI runners may need the two-step workflow.

What the Numbers Say

To see the effect, I measured two small programs on JDK 25.0.4.1: the stream example above, and a slightly busier one that uses records, regex, collectors and a thread pool. Each case ran 25 times, and the chart shows the median wall-clock time in milliseconds.

Measured by me on a single-vCPU Linux x86-64 sandbox, JDK 25.0.4.1 (Temurin), 25 runs per case, median shown. Time includes JVM start and exit. Tiny programs only, so treat this as direction, not proof for your service.

The stream program went from 75 ms to 47 ms, about 37% faster. The busier program dropped from 151 ms to 79 ms, roughly 48% faster. These results match the official picture. For example, JEP 483 reports Spring PetClinic starting in 2.604 seconds instead of 4.486 seconds, a 42% improvement. In addition, JEP 515 reports a 19% gain on a tiny warmup example, from 90 ms to 73 ms.

The Real Trade-Off

Leyden is not “GraalVM without the cost”. It is a different bargain, and it has its own bills.

What You Still Pay

First, you still ship and run a full JVM, so memory use stays JVM-sized. Second, you add a training step to your build, and a poor training run gives weaker results. As SoftwareMill’s JEP 514 and 515 explainer points out, training quality directly affects the gain. Third, the cache is tied to your setup. Per JEP 483, as summarized by BackendBytes, training and production must share the same JDK release, OS and CPU architecture.

Finally, there is file size. My caches were 10.0 MB and 12.1 MB for tiny programs. A third-party breakdown lists about 130 MB for PetClinic, so budget for it in container images.

What JEP 544 May Change

The next step is to cache optimized native code, not only profiles. If it lands as planned, startup gains should grow. BackendBytes, summarizing the JEP’s benchmarks on five framework apps with two cores, reports a rise from about 50 to 70% faster with the cache alone to about 65 to 80% with AOT code added.

Reported startup-time reduction ranges, from BackendBytes’ summary of JEP 544 (I could not open the JEP page directly). Pre-release figures from the Leyden team’s own benchmarks, so wait for independent tests.

The draft JEP also says support starts with x64 and AArch64 processors only.

Leyden or GraalVM?

Leyden AOT cacheGraalVM Native Image
Runs onStandard HotSpot JVMStandalone native binary
StartupFaster, still JVM speedMilliseconds
MemoryAbout JVM levelMuch lower
Code changesNone expectedMetadata for reflection and similar
Dynamic featuresKeptRestricted by closed world
MaturityShipping in steps, code caching proposedMature, monthly releases

In practice, start with Leyden if you want a cheap win and zero compatibility risk. Choose Native Image when memory density or tiny start times matter most, and you can afford the build work.

What We Have Learned

Project Leyden speeds up Java by moving startup work into a training run and saving it in an AOT cache. Class loading and linking arrived in JDK 24, while one-command setup and method profiling arrived in JDK 25 LTS, and ZGC support followed in JDK 26. Full AOT code compilation is not in JDK 27, because JEP 544 is proposed for JDK 28. In my small tests, the cache cut startup by about 37% and 48%, which fits the official 42% PetClinic figure. The trade-off is clear: you keep the JVM, its tools and its flexibility, but you also keep its memory use, and you must manage a training run and a cache file. In short, Leyden is the low-risk first step, and Native Image remains the choice for extreme footprint goals.

Eleftheria Drosopoulou

Eleftheria is an Experienced Business Analyst with a robust background in the computer software industry. Proficient in Computer Software Training, Digital Marketing, HTML Scripting, and Microsoft Office, they bring a wealth of technical skills to the table. Additionally, she has a love for writing articles on various tech subjects, showcasing a talent for translating complex concepts into accessible content.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button