A team compiles `OrderService.java`, which uses `StructuredTaskScope` (a preview API in Java 21), with `javac --release 21 --enable-preview`. Their CI pipeline caches the resulting `.class` files across builds. After the JDK is bumped to 21.0.4 in the same major version, the cached class fails to load with an error that looks like build corruption. What's actually failing, and why doesn't matching the JDK's major version save them?
When javac --enable-preview compiles a class using a preview feature, it stamps a specific marker into the class file itself: the minor-version field is set to 0xFFFF, a value no ordinary Java class file ever carries. Every JVM's class-file verifier checks that field when loading a class, and a class stamped 0xFFFF is only accepted when two conditions both hold: the running JVM is the exact same feature release that produced it, and that JVM is also launched with --enable-preview. "Exact same feature release" is stricter than "same major version" in the way that trips this team — the minor-version tag isn't checking "Java 21 or later", it's tied to that one specific feature release's preview API shape, and a patch update within the same major version (21 to 21.0.4) does not automatically satisfy it if anything about the JVM's own preview handling shifted between those builds, or if the runtime launching it is missing --enable-preview. The failure looks like a corrupt build because the error message is a generic class-loading failure, but it's actually the verifier correctly refusing to load a version-locked preview artifact under conditions it wasn't produced for.