Living with preview and incubator features
What --enable-preview commits you to, and why it is not for production.
Open this lesson in the learning hubKey points
- A preview feature is complete but not permanent. It may change or be withdrawn in the next release - string templates were previewed in 21 and 22, then removed in 23.
- Preview class files are marked with the exact JDK version that produced them, and they will refuse to run on any other version, even a newer one.
- That is deliberate: it stops preview bytecode leaking into long-lived artefacts. It also means every JDK bump forces a full recompile of that code.
- Incubator modules are weaker still - the Vector API has incubated for years. They live in
jdk.incubator.*and need an explicit--add-modules. - The practical rule: preview features belong in experiments and internal tools, never in a library other people depend on, and never in an artefact you cannot rebuild on demand.
- If you do adopt one, isolate it in a single module with a documented fallback, so a withdrawal is a contained change rather than a rewrite.
Example
# Compiling and running with a preview feature - both flags are required.
$ javac --release 23 --enable-preview Main.java
$ java --enable-preview Main
# Forgetting it at runtime:
# Preview features are not enabled for Main (class file version 67.65535).
# Try running with '--enable-preview'
# The 65535 minor version is the marker. It PINS the class file to that
# exact JDK - a JDK 23 preview class will not run on JDK 24, by design.
---
# Gradle
tasks.withType(JavaCompile).configureEach {
options.compilerArgs += '--enable-preview'
}
tasks.withType(Test).configureEach { jvmArgs '--enable-preview' }
tasks.named('bootRun') { jvmArgs '--enable-preview' }
# Miss any one of these and it fails only in that context.
---
# Incubator modules need an explicit --add-modules:
$ javac --add-modules jdk.incubator.vector Main.java
$ java --add-modules jdk.incubator.vector Main
# WARNING: Using incubator modules: jdk.incubator.vector
---
# THE STRING TEMPLATE LESSON:
#
# JDK 21 preview teams adopted it
# JDK 22 second preview
# JDK 23 REMOVED that code no longer compiles at all
#
# Not a warning, not a deprecation - removed. That is what preview means,
# and it is exactly why it does not belong in a shipped library.
# A defensible policy:
# production service no preview features
# published library absolutely no preview features
# internal tooling acceptable if you can rebuild on demand
# experiments and spikes the intended audience
Preview bytecode is pinned to the exact JDK that built it and can be withdrawn outright - string templates were, in one release.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Java 23 Course course, and every lesson in it is listed on the Java 23 Course contents page.