JEP 483: Ahead-of-Time Class Loading & Linking. Project Leyden in JDK 24

Transcript 


In this video, we'll look at JEP 483: Ahead-of-Time Class Loading and Linking, which is targeted for JDK 24 and marks the initial introduction of Project Leyden into the mainline OpenJDK. When Java applications start, necessary application classes and core JVM classes must be loaded and initialized. There can be thousands of classes, so this process affects the startup times of Java applications. The worst part is that this process repeats every time the application starts.

One way to deal with this issue is to use Application Class Data Sharing (AppCDS), a JVM feature that reads and parses a set of application and JVM classes, storing this data in a read-only archive. When the application starts, the JVM reads the data from the archive, speeding up the startup process. Ahead-of-Time (AOT) class loading and linking goes even further. It not only reads and parses but also loads and links classes, storing this data in an AOT cache. As a result, the JVM has even less work to do at startup. This feature aligns with the overall goal of Project Leyden, which aims to shift some computations from the production run to earlier stages, such as trial runs. AOT class loading and linking is the first step towards introducing Project Leyden to OpenJDK.

You create the AOT cache once, and it can be reused every time your application starts. This feature is compatible with any Java application and doesn’t require changes to the application code. The only requirement is to perform a training run for your application to record its AOT configuration. The more efficient the training run, the better the resulting AOT cache. The training run should mimic the production run, allowing the application to fully configure itself and execute production code paths.

Now, let’s try this feature with the early access builds of JDK 24. For this experiment, I’ve downloaded early access builds of JDK 24, which you can also get for your platform. Note that the results we’ll get are preliminary and may change when stable builds are released. But we’re just testing the waters, right? Take any Spring app you like. I’m using a Spring Boot-based CRUD application that manages personal tasks. It’s a simple app with basic functionality. You can follow along or experiment with your own application.

Let’s first create a JAR file using maven clean package. Running the executable JAR in production is not recommended by the Spring team, so we’ll create an exploded JAR instead. For this, we’ll use the Djarmode=tools option to extract the JAR. Now we have our extracted JAR with the lib subdirectory and the JAR file itself. Let’s first run the application with the JAR file to see how fast it starts without any optimizations. As you can see, the application started in about two seconds.

All right, let’s get down to business. To create an AOT cache, we need to perform two steps (although it’s planned to merge them into one step in the future). First, conduct a trial run of your application with two flags: -XX:AOTMode=record and -XX:AOTConfiguration to record its AOT configuration into the file app.aotconf. Now, push some buttons in the application so it performs useful operations. Next, use the configuration file to create the cache. For this, use three flags: -XX:AOTMode=create, -XX:AOTConfiguration pointing to app.aotconf, and -XX:AOTCache to create the cache named app.aot. This step doesn’t run the application; it only creates the cache.

Now we can run the application. This time, we only need one flag: -XX:AOTCache pointing to the cache file we created earlier. As you can see, the application started in just one second, which is pretty cool.

In this video, we explored a new JDK feature, Ahead-of-Time Class Loading and Linking, aimed at reducing the startup times of Java applications. If you like this video, subscribe to our channel. And until next time!

Summary

JEP 483 introduces Ahead-of-Time (AOT) Class Loading and Linking in JDK 24, which enhances Java application startup times by loading and linking classes ahead of time and storing them in a reusable AOT cache. This feature, part of Project Leyden, reduces the JVM's workload during startup without requiring changes to application code, though a training run mimicking production is needed to create an efficient cache. Early tests with a Spring Boot app showed significant improvements, cutting startup time from two seconds to just one second.

About Catherine

Java developer passionate about Spring Boot. Writer. Developer Advocate at BellSoft

Social Media

Videos
card image
Apr 2, 2026
Java Memory Options You Need in Production

JVM memory tuning can be tricky. Teams increase -Xmx and assume the problem is solved. Then the app still hits OOM. Because maximum heap size is not the only thing that affects memory footprint. The JVM uses RAM for much more than heap: metaspace, thread stacks, JIT/code cache, direct buffers, and native allocations. That’s why your process can run out of memory while heap still looks “fine”. In this video, we break down how JVM memory actually works and how to control it with a minimal, production-safe set of flags. We cover heap sizing (-Xms, -Xmx), dynamic resizing, direct memory (-XX:MaxDirectMemorySize), and total RAM limits (-XX:MaxRAMPercentage) — especially in containerized environments like Docker and Kubernetes. We also explain GC choices such as G1, ZGC, and Shenandoah, when defaults are enough, and why GC logging (-Xlog:gc*) is mandatory before tuning. Finally, we show how to diagnose failures with heap dumps and OOM hooks. This is not about adding more flags. It’s about understanding what actually consumes memory — and making decisions you can justify in production.

Videos
card image
Mar 26, 2026
Java Developer Roadmap 2026: From Basics to Production

Most Java roadmaps teach tools. This one teaches order — the only thing that actually gets you to production. You don’t need to learn everything. You need to learn the right things, in the right sequence. In this video, we break down a practical Java developer roadmap for 2026 — from syntax and OOP to Spring, databases, testing, and deployment. Structured into 8 levels, it shows how real engineers grow from fundamentals to production-ready systems. We cover what to learn and what to ignore: core Java, collections, streams, build tools, Git, SQL and JDBC before Hibernate, the Spring ecosystem, testing with JUnit, and deployment with Docker and CI/CD. You’ll also understand why most developers get stuck — jumping into frameworks too early, skipping SQL, or treating tools as knowledge. This roadmap gives you a clear path into real-world Java development — with priorities, trade-offs, and production context.

Further watching

Videos
card image
Apr 30, 2026
Java Flight Recorder Tutorial: How to Profile Java Applications

High CPU, GC spikes, or slow startup are common production issues, but logs and metrics don’t always reveal what the JVM is actually doing. Java Flight Recorder (JFR) provides a precise, low-overhead view of JVM behavior, safe for use even in production environments. In this video, you’ll learn how to use JFR to identify real bottlenecks such as CPU hotspots, memory allocation pressure, thread contention, and I/O stalls. We walk through the full workflow, including starting recordings with JVM flags, controlling them via jcmd, running JFR inside Docker containers, and attaching to live systems using ephemeral containers. Then we analyze a real Spring Boot recording in JDK Mission Control, breaking down GC behavior, allocation patterns, thread states, and method-level hotspots. If you want to move from symptoms to root cause with more confidence, this approach will help. Full article with commands and examples: [https://bell-sw.com/blog/how-to-profile-java-applications-with-jfr-beginner-s-guide/](https://bell-sw.com/blog/how-to-profile-java-applications-with-jfr-beginner-s-guide/)

Videos
card image
Apr 22, 2026
Dynamic SQL Queries with Spring Data JPA in 6 Minutes

If your repository layer has multiple queries for different filter combinations, your data access logic is already getting harder to maintain. In this video, we implement dynamic SQL queries in Spring Data JPA using Specifications — a composable approach that helps avoid query duplication and keeps your filtering logic clean. We build a flexible filtering system with optional parameters (category, language, format, price) and show how Specification.unrestricted() skips empty filters, while Specification.allOf(...) combines them into a single query. We also address a common issue: string-based field access. It’s fragile and can break at runtime when your model changes. Using the JPA Static Metamodel, we move to compile-time safety. The result is a cleaner, more maintainable way to implement dynamic filtering in Spring-based applications.

Videos
card image
Apr 8, 2026
Best Oracle Java Alternatives in 2026 Comparison of OpenJDK Distributions

A comparison of major OpenJDK distributions (Temurin, Liberica, Zulu, Corretto, Semeru, etc.), covering who maintains them, how updates are delivered, and what lifecycle guarantees they provide. We also explain why upstream OpenJDK isn’t production-ready and how your vendor choice impacts real-world systems. Useful for Spring Boot, containers, and Kubernetes to avoid hidden risks and choose the right runtime.