Java 27 shipped on September 15. You have already heard about the post-quantum TLS update and compact object headers. There is a third feature that barely made the headlines: JEP 544, Ahead-of-Time Code Compilation. It lands in JDK 27 and it directly addresses the complaint that has followed Java microservices for fifteen years — slow cold starts — without requiring you to rewrite a single line of code or wrestle with native image metadata.
What JEP 544 Actually Does
The idea is straightforward. Java’s JIT compiler is excellent at peak throughput but needs time to warm up — it has to observe which methods are “hot” before it compiles them to native code. On every cold start, you pay that warmup tax again. JEP 544 moves that compilation work into a training run you do once at build time.
During the training run, HotSpot records which classes load and which methods get hot, compiles those methods to native code, and stores everything in an AOT cache file. When your app starts in production, it loads that pre-compiled code instantly. No JIT warmup. No cold start penalty.
The numbers are real: in microservice-like environments with constrained CPU cores, JEP 544 reduces startup time by 65-80%. A javac benchmark repeatedly compiling 50 source files shows a 75% total improvement — 30% from the AOT cache alone and another 45% on top when AOT-compiled code is added.
How to Use It
JDK 27 also ships JEP 514, which simplifies the original three-step workflow into two steps. Here is the full picture:
Original three-step workflow (JEP 544):
# Step 1: Training run — records hot methods and class loading
java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf -cp app.jar com.example.App
# Step 2: Build the AOT cache from training data
java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:AOTCache=app.aot -cp app.jar
# Step 3: Production run — loads pre-compiled native code instantly
java -XX:AOTCache=app.aot -cp app.jar com.example.App
JEP 514 shortcut (also in JDK 27) — collapses steps 1 and 2:
# Combines training + cache creation in one command
java -XX:AOTCacheOutput=app.aot -cp app.jar com.example.App
# Production run is identical
java -XX:AOTCache=app.aot -cp app.jar com.example.App
Want to verify the cache is actually being used? Add -XX:AOTMode=on to the production command. The JVM will hard-fail if the cache does not exist or the setup is mismatched — useful for CI validation gates.
The Catches You Need to Know
Environment matching is strict. The training run and every production run must use the same CPU architecture and feature flags. AOT code compiled for an x64 CPU with AVX-512 will not run on an x64 machine without AVX-512. The same applies to the garbage collector — GC-specific read/write barriers are baked into the native code, so you cannot switch GCs between training and production.
Tooling is not there yet. The Hacker News discussion on JEP 544 put it plainly: the tooling for doing these sorts of training runs does not really exist, and developers end up needing to do something more bespoke as part of their build pipeline. There is no mainstream Maven or Gradle plugin as of JDK 27 release. You are writing your own build stage scripts. JEP 514 helps locally, but CI/CD integration still requires manual wiring.
Workload drift is a graceful failure. If your traffic patterns change significantly after training — a new endpoint gets hot that was not exercised during the training run — HotSpot deoptimizes the stale AOT code and falls back to JIT compilation for those methods. This does not crash your application, but you lose the startup benefit for those paths until you retrain.
JEP 544 vs GraalVM Native Image
Java developers have had GraalVM native image for years. JEP 544 is not a replacement — it is a different tradeoff:
| JEP 544 (HotSpot AOT) | GraalVM Native Image | |
|---|---|---|
| Startup reduction | 65-80% | Up to 97% |
| Peak throughput | Full JIT performance | ~20% lower |
| Build time | Seconds | 5-15 minutes |
| Reflection support | Works natively | Requires metadata |
| Workload adaptability | Yes — re-JITs on drift | No — fully static |
If you are running serverless functions with pod lifetimes under 15 minutes and startup SLA is paramount, GraalVM still wins on raw cold-start numbers. For long-running microservices where peak throughput matters and native image reflection limitations keep breaking your framework, JEP 544 is the cleaner path. No metadata, no build time cost, no peak performance penalty.
Framework Support Today
Spring Boot 3.3 and later support Leyden AOT caching. Spring Boot AOT cache guide covers the integration. The Paketo Buildpacks team has an open Epic for first-class AOT cache support in OCI images, meaning containerized Spring apps will get this more automatically in coming months. Spring Boot 4.x is expected to ship deeper JEP 544 integration. Quarkus and Micronaut teams are watching — for users who found GraalVM native image too brittle, JEP 544 is the obvious lower-friction alternative.
Bottom Line
JEP 544 is ready to experiment with today on JDK 27. The commands work. The numbers are real. The limitation is the surrounding toolchain, not the JVM itself. If your team can wire a training-run stage into your Docker build and CI pipeline, you can claim 65-80% startup reduction right now. If you are waiting for a Gradle plugin and a one-liner, that is probably 6-12 months out.
Start with the JEP 544 spec for the full technical picture, then check the Spring Framework AOT cache docs if you are running Spring. The cold start problem is not solved, but for the first time it is addressable entirely within the standard JVM.













