Skip to content

How Java 26's AOT Object Caching Improves Startup Performance

Problem

My Java microservice takes 15 seconds to start. Every time it scales up, there’s a noticeable delay before it can handle requests. The JVM needs time to:

  • Load classes
  • Initialize static fields
  • JIT compile hot paths
  • Build internal data structures

I wanted to understand how Java 26’s AOT Object Caching could help.

Environment

  • Java 26 (non-LTS)
  • Spring Boot 3.x microservice
  • Deployed on Kubernetes

What Is AOT Object Caching?

AOT (Ahead-of-Time) Object Caching is part of Project Leyden, Java’s initiative to improve startup and warmup times.

Here’s the idea:

Before AOT Caching
Application Start
Load Classes
Initialize Objects (slow!)
JIT Compilation
Ready to Serve
With AOT Caching
Application Start
Load Classes
Load Cached Objects (fast!)
Ready to Serve

The key insight: many objects don’t change between runs. Configuration maps, immutable data structures, static caches - these can be computed once and loaded directly.

What Changed in Java 26?

JEP 516 made AOT caching work with any garbage collector. Previously, it only worked with G1 or Serial GC.

GC Support Comparison
Before Java 26:
┌─────────────┐
│ AOT Cache │ → Only G1, Serial GC
└─────────────┘
After Java 26:
┌─────────────┐
│ AOT Cache │ → G1, ZGC, Shenandoah, Serial, Parallel
└─────────────┘

This matters because modern cloud applications often use ZGC for low-latency requirements. Now they can benefit from AOT caching too.

How It Works

The caching process has two phases:

Phase 1: Build Time

During the build, identify objects suitable for caching:

Example Cached Objects
// Immutable configuration - perfect for caching
private static final Map<String, Config> CONFIG_MAP =
loadFromFiles(); // Runs at build time
// Static lookup tables - good candidate
private static final List<Rule> VALIDATION_RULES =
compileRules(); // Runs at build time

Phase 2: Runtime

At startup, load the pre-computed cache directly:

Cache Loading Flow
Build Time Runtime
│ │
▼ ▼
Compute Objects Load from Cache
│ (milliseconds)
▼ │
Serialize to Disk ▼
│ Objects Ready
AOT Cache File

No recomputation. No initialization overhead.

When Does This Help?

AOT caching helps most when:

  1. Cloud-native applications - Fast scaling matters
  2. Serverless functions - Cold start latency is critical
  3. Microservices - Frequent scale up/down cycles
  4. Development - Faster restarts during testing

When it doesn’t help much:

  • Long-running monoliths
  • Applications with mostly dynamic data
  • Systems where startup time isn’t a concern

How to Use It

Enable AOT caching with JVM flags:

Enable AOT Caching
# Create cache during first run
java -XX:AOTCache=./app.aot -jar myapp.jar
# Use cache on subsequent runs
java -XX:AOTCache=./app.aot -XX:AOTCacheLoad -jar myapp.jar

The exact flags and API are still evolving. Check the JEP 516 documentation for current syntax.

Why This Matters

Java has always been criticized for slow startup. GraalVM native images solve this but require significant code changes. AOT caching is a middle ground:

Startup Time Comparison
Traditional JVM: ████████████████████ 15s
AOT Cache: ████████ 6s
Native Image: ███ 2s
Trade-offs:
Native Image → Best startup, but requires refactoring
AOT Cache → Good startup, minimal code changes
Traditional → Slow startup, no changes needed

Project Leyden’s goal is to bring native-image-like performance without the constraints. AOT Object Caching is a step toward that goal.

Summary

In this post, I showed how Java 26’s JEP 516 AOT Object Caching improves startup performance. The key points are:

  • Cached objects load directly at runtime, skipping initialization
  • Now works with any GC (including ZGC)
  • Most beneficial for cloud-native, serverless, and microservice architectures
  • Part of Project Leyden’s push toward faster JVM startup

This is a stepping stone. Watch Project Leyden for more startup optimizations in future releases.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments