<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/java-s-new-aot-cache-feature-is-in-a-rough-state-xatp3n3gd" -->

---
title: Java's new AOT cache feature is in a rough state | daily.dev
description: Java's AOT cache, meant to speed up startup for free, is fragile and poorly documented in practice. It can crash the JVM with SIGILL errors when an app is...
canonical: https://daily.dev/posts/java-s-new-aot-cache-feature-is-in-a-rough-state-xatp3n3gd
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Java's new AOT cache feature is in a rough state | daily.dev
og:description: Java's AOT cache, meant to speed up startup for free, is fragile and poorly documented in practice. It can crash the JVM with SIGILL errors when an app is...
og:url: https://daily.dev/posts/java-s-new-aot-cache-feature-is-in-a-rough-state-xatp3n3gd
og:image: https://api.daily.dev/og/posts/XaTp3n3gD.png
og:image:alt: Java's new AOT cache feature is in a rough state
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Java's new AOT cache feature is in a rough state

**[Hacker News](https://daily.dev/sources/hn)** · 26 min read · 0 upvotes · 1 comments

## Summary

Java's AOT cache, meant to speed up startup for free, is fragile and poorly documented in practice. It can crash the JVM with SIGILL errors when an app is trained on a CPU with AVX features not present on the target machine, since it generates CPU-specific adapter code. Disabling this requires the undocumented flag '-XX:-AOTAdapterCaching'. Class linking also silently breaks with incubating modules, GraalVM's extra modules, or JDK 26's final-field-mutation warnings. Security agents like SentinelOne block the cache entirely and leak error output to stdout, breaking scripts that parse command output.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://xpipe.io/blog/java-aot-cache>

## Questions this post answers

### Why does my Java app crash with SIGILL in AdapterBlob when using the AOT cache on a different machine than it was built on?

The AOT cache with class linking generates adapter caches containing small pieces of native machine code tied to the CPU features of the build machine, such as AVX support. If the target system lacks one of those CPU features (e.g. trained on a 13th gen Intel CPU, run on a 12th gen one), the JVM crashes with a SIGILL fatal error referencing an AdapterBlob frame.

_Anyone shipping Java apps across mixed hardware tracks JDK AOT cache fixes like this on daily.dev._

### How do I disable AOT adapter caching in the JDK to avoid CPU feature mismatch crashes?

Pass the undocumented diagnostic flags '-XX:+UnlockDiagnosticVMOptions -XX:-AOTAdapterCaching' during AOT cache generation. This option defaults to false but gets turned on automatically ('ergonomic') whenever the cache contains AOT-linked classes, so it must be explicitly disabled to prevent crashes on systems with different CPU features. The issue was reported as JDK-8388703, and JDK 27 plans to require an exact CPU feature match instead.

_Developers rolling out JVM startup optimizations follow JDK flag changes like this on daily.dev before they ship._

### Why does a JVMTI agent like an EDR tool break my Java application's AOT cache and command output?

A JVMTI ClassFileLoadHook agent, such as the one SentinelOne attaches to every Java process, prevents the AOT cache from loading if it contains AOT-linked classes. This is not a fatal error, but the resulting messages print to stdout rather than stderr, which breaks scripts that parse a command's output, like 'API_KEY=$(myapp generate-key)'. The fix is running with '-Xlog:disable' or redirecting logs to stderr in production builds.

_Teams debugging unexpected CLI output in production track JVM logging quirks like this on daily.dev._

## Community take

How the wider developer community reacted, aggregated from 1 discussion and 35 comments across hackernews (as of 2026-10-30).

**TL;DR:** The AOT cache is seen as an immature, early-stage feature with real sharp edges (CPU-feature mismatches, poor diagnostics, interactions with modules/agents), though some argue this is normal for the JDK's incremental delivery style and that it's already valuable for internal deployments.

**Sentiment:** 10% positive · 55% mixed · 35% skeptical

**The case for**

- Some note the AOT cache already helps real production use cases despite rough edges, especially for internal deployments where developers control the environment.
- Unlike GraalVM's native image, the AOT cache reportedly still allows modifying the classpath/module path at runtime rather than requiring a fully closed world.
- JDK features are intentionally released piecemeal so they can be useful early rather than waiting for a polished final form.

**The pushback**

- CPU-feature mismatches between training and production should trigger a warning or safe fallback to JIT instead of crashing.
- The cache-busting logic is too coarse, busting the cache on any CPU feature difference rather than only relevant ones.
- Broader frustration that Java deployment tooling (Maven/Gradle plugins, jlink) remains messy compared to Rust, Go, or even modern .NET.
- One commenter who tried AOT/JIT caching approaches (OpenJ9, Azul, OpenJDK) found the payoff underwhelming compared to simply rewriting the service in Rust.

**By community**

- hackernews (mixed): Discussion mixes practical frustration with the AOT cache's rough edges against defenses that this is expected for an incrementally-delivered JDK feature already providing value internally.

**Hottest debate:** Whether Java's overall deployment/startup story is fundamentally messy compared to other ecosystems, or whether critics are unfairly singling out Java for problems that exist everywhere.

**Open questions**

- Will cache invalidation logic be refined to bust only on CPU features that actually matter rather than any difference?
- How will the AOT cache evolve to support external/third-party deployment scenarios once machine-code caching lands in JDK 28?

**Highlights**

> I wonder if this should trigger a warning (or even an error) at application startup whenever the CPU architectures differ. IMHO, that would be much better than running into crashes and having to figure out the cause yourself.
> — [florieger on hackernews · 2 comments](https://news.ycombinator.com/item?id=50289693)

> That, and I think the cache busting based on CPU/environment probing logic will need to be significantly improved. Any difference in CPU features should not bust the cache; specific differences should bust the cache. There also might be a need for "downgrading" cross-compilation profiles a la "don't compile/AOT-cache this app for the current CPU, compile/cache it for <the kind of CPU that I have 10k EC2 instances running>". You'd think that would be easier to achieve by just compiling on a production-like machine, and you'd be disappointed by the number of shops running Java apps hand-built on a Windows laptop across millions of cloud Linux cores.
> — [zbentley on hackernews · 1 comments](https://news.ycombinator.com/item?id=50294194)

> I spent a couple weeks trying to bolt this on to our setup to support a more serverless style approach. OpenJ9 (sadly) really didn't work out well, perhaps we run in a way they don't optimize for. Azul and OpenJDK's approaches helped - but it is quite intrusive (you need a profiling run), and the absolute benefits aren't that great. It's mostly doing classpath stuff at present, and not really AOT work on machine code (though that is in the pipeline). All in all, I wasn't particularly impressed with the outcome. Obviously GraalVM has more headroom, but that's an even more intrusive change. When compared with a Rust port of our service, the delta of the efforts is absolutely astronomical. Ridiculous performance, near-instant startup, radically less memory consumption. I mean - duh - but nonetheless, when I contrast the effort vs payback, it's very hard for me to want to invest so much in techniques that have so little payback (graal) when I can put that into an approach that leaves me in a much better place long-term. If I had mountains of legacy, obviously I couldn't do that, but in my situation it seems like a much more attractive option.
> — [switchbak on hackernews · 1 comments](https://news.ycombinator.com/item?id=50296009)

> For the past several years, Java features are released piecemeal, with each piece released as soon as it can be useful to some significant portion of users or users who can offer useful feedback (and when it's not expected to restrict future pieces). The AOT cache is already used in production despite not being as user-friendly as it could be, because the companies using it find it valuable. The first use case is the very common one (for Java) where developers control deployment (internal deployment). The last basic building block, caching machine code, will be released next year in JDK 28, and then the feature is likely to evolve to better support other use cases, such as external deployment.
> — [pron on hackernews · 1 comments](https://news.ycombinator.com/item?id=50290362)

> I saw this on Reddit, and as expected, the replies from the Java community were quite hostile. Sometimes it feels like Java developers have never left their own ecosystem and have never seen how easy some things (like deployment) are on other platforms. Especially Java's way of deploying applications has hindered not only Java but also alt JVM languages like Kotlin and Scala.
> — [pregnenolone on hackernews · 1 comments](https://news.ycombinator.com/item?id=50292866)

**Source threads**

- [hackernews](https://news.ycombinator.com/item?id=50242509) · 75 points · 35 comments

## Community discussion

Top comments from developers on daily.dev.

**@ejboy** · 0 upvotes

> I've been experimenting with Spring Boot optimizations, including the JDK AOT cache. It can improve startup performance, but as this article shows, there are important caveats.
>
> My experiments and benchmarks: [https://pvrlabs.xyz/articles/spring-boot-jdk27-optimizations.html](https://pvrlabs.xyz/articles/spring-boot-jdk27-optimizations.html)

## Similar posts on daily.dev

- [A Guide to Ahead-of-Time Cache in the Java](https://daily.dev/posts/a-guide-to-ahead-of-time-cache-in-the-java-xfptxkmvl) · Baeldung · 3 upvotes · 0 comments
- [JEP 544: Ahead-of-Time Code Compilation](https://daily.dev/posts/jep-544-ahead-of-time-code-compilation-hnqenmv6i) · Inside Java · 0 upvotes · 0 comments
- [Ahead-of-Time Class Loading & Linking](https://daily.dev/posts/ahead-of-time-class-loading-linking-yftlbv7es) · Baeldung · 0 upvotes · 0 comments
- [How is Leyden improving Java Performance? Part 2 of](https://daily.dev/posts/how-is-leyden-improving-java-performance-part-2-of-k95xs5i7z) · Foojay.io · 1 upvotes · 0 comments
- [Run Into the New Year with Java’s Ahead-of-Time Cache Optimizations – Inside.java](https://daily.dev/posts/run-into-the-new-year-with-java-s-ahead-of-time-cache-optimizations-inside-java-75zsl41gf) · Inside Java · 1 upvotes · 0 comments

---

Tags: [#java](https://daily.dev/tags/java), [#jvm](https://daily.dev/tags/jvm)

[View this post on daily.dev](https://daily.dev/posts/java-s-new-aot-cache-feature-is-in-a-rough-state-xatp3n3gd)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Java's new AOT cache feature is in a rough state","url":"https://daily.dev/posts/java-s-new-aot-cache-feature-is-in-a-rough-state-xatp3n3gd","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/java-s-new-aot-cache-feature-is-in-a-rough-state-xatp3n3gd"},"datePublished":"2026-10-29T16:22:11.801Z","dateModified":"2026-10-30T03:24:38.749Z","description":"Java's AOT cache, meant to speed up startup for free, is fragile and poorly documented in practice. It can crash the JVM with SIGILL errors when an app is...","image":"https://media.daily.dev/image/upload/s--58gMhC4P--/f_auto/v1722860399/public/Placeholder%2012","thumbnailUrl":"https://media.daily.dev/image/upload/s--58gMhC4P--/f_auto/v1722860399/public/Placeholder%2012","isAccessibleForFree":true,"articleSection":"Hacker News","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Hacker News","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/hn","url":"https://daily.dev/sources/hn"},"commentCount":1,"discussionUrl":"https://daily.dev/posts/java-s-new-aot-cache-feature-is-in-a-rough-state-xatp3n3gd","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":1}],"keywords":"java,jvm","timeRequired":"PT26M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Hacker News","item":"https://daily.dev/sources/hn"},{"@type":"ListItem","position":3,"name":"Java's new AOT cache feature is in a rough state"}]}
{"@context":"https://schema.org","@type":"WebPage","@id":"https://daily.dev/posts/java-s-new-aot-cache-feature-is-in-a-rough-state-xatp3n3gd","comment":[{"@type":"Comment","text":"I’ve been experimenting with Spring Boot optimizations, including the JDK AOT cache. It can improve startup performance, but as this article shows, there are important caveats.\nMy experiments and benchmarks: https://pvrlabs.xyz/articles/spring-boot-jdk27-optimizations.html","datePublished":"2026-10-31T02:30:27.669Z","url":"https://daily.dev/posts/XaTp3n3gD#c-pX5gQrTuT","author":{"@type":"Person","name":"Ted K","url":"https://daily.dev/ejboy","image":"https://media.daily.dev/image/upload/s--PzSRqJKu--/f_auto/v1787843390/avatars/avatar_Szw3t3q8eJYj5aTperuyF?_a=BAMAMicg0"}}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/java-s-new-aot-cache-feature-is-in-a-rough-state-xatp3n3gd#faq","mainEntity":[{"@type":"Question","name":"Why does my Java app crash with SIGILL in AdapterBlob when using the AOT cache on a different machine than it was built on?","acceptedAnswer":{"@type":"Answer","text":"The AOT cache with class linking generates adapter caches containing small pieces of native machine code tied to the CPU features of the build machine, such as AVX support. If the target system lacks one of those CPU features (e.g. trained on a 13th gen Intel CPU, run on a 12th gen one), the JVM crashes with a SIGILL fatal error referencing an AdapterBlob frame. Anyone shipping Java apps across mixed hardware tracks JDK AOT cache fixes like this on daily.dev."}},{"@type":"Question","name":"How do I disable AOT adapter caching in the JDK to avoid CPU feature mismatch crashes?","acceptedAnswer":{"@type":"Answer","text":"Pass the undocumented diagnostic flags '-XX:+UnlockDiagnosticVMOptions -XX:-AOTAdapterCaching' during AOT cache generation. This option defaults to false but gets turned on automatically ('ergonomic') whenever the cache contains AOT-linked classes, so it must be explicitly disabled to prevent crashes on systems with different CPU features. The issue was reported as JDK-8388703, and JDK 27 plans to require an exact CPU feature match instead. Developers rolling out JVM startup optimizations follow JDK flag changes like this on daily.dev before they ship."}},{"@type":"Question","name":"Why does a JVMTI agent like an EDR tool break my Java application's AOT cache and command output?","acceptedAnswer":{"@type":"Answer","text":"A JVMTI ClassFileLoadHook agent, such as the one SentinelOne attaches to every Java process, prevents the AOT cache from loading if it contains AOT-linked classes. This is not a fatal error, but the resulting messages print to stdout rather than stderr, which breaks scripts that parse a command's output, like 'API_KEY=$(myapp generate-key)'. The fix is running with '-Xlog:disable' or redirecting logs to stderr in production builds. Teams debugging unexpected CLI output in production track JVM logging quirks like this on daily.dev."}}]}
```

