October review: choose a supported target first
Updated October 11, 2026: The original feature table was incorrect and has been replaced with the official JDK 26 list. Several entries described JDK 24 features, and the value-class examples did not describe released JDK 26 functionality.
JDK 26 has been superseded. Its archived OpenJDK builds do not contain the latest security fixes and are not recommended for production. This guide remains useful for understanding the release and reproducing migration experiments, not for selecting those archived binaries for a new deployment.
For production planning, distinguish two paths:
- JDK 25 LTS: a long-term-support baseline when using a vendor distribution with an appropriate maintenance policy.
- JDK 27: the current feature-release option; the official download page identifies its GA builds as production-ready.
LTS support duration, patches, licensing, and platform availability depend on the distributor. Confirm those details before choosing a runtime image. If a vendor still supports JDK 26, verify its actual security-update policy rather than assuming archived OpenJDK binaries are maintained.
What actually shipped in JDK 26
The OpenJDK JDK 26 project page lists these ten JEPs:
| JEP | Feature | Status in JDK 26 |
|---|---|---|
| 500 | Prepare to Make Final Mean Final | Delivered; prepares restrictions on deep-reflection mutation of final fields |
| 504 | Remove the Applet API | Removed |
| 516 | Ahead-of-Time Object Caching with Any GC | Delivered |
| 517 | HTTP/3 for the HTTP Client API | Delivered |
| 522 | G1 GC: Improve Throughput by Reducing Synchronization | Delivered |
| 524 | PEM Encodings of Cryptographic Objects | Second preview |
| 525 | Structured Concurrency | Sixth preview |
| 526 | Lazy Constants | Second preview |
| 529 | Vector API | Eleventh incubator |
| 530 | Primitive Types in Patterns, instanceof, and switch | Fourth preview |
“Delivered” does not imply that a performance improvement will help every application. Preview and incubator features remain separate adoption decisions, not prerequisites for upgrading the runtime.
Corrections to earlier release attributions
JEPs 488, 492, 494, 495, 496, 497, 499, 487, and 489 belong to JDK 24, not JDK 26. In particular, JEP 496 is the quantum-resistant Module-Lattice-Based Key Encapsulation Mechanism, and JEP 497 is the quantum-resistant Module-Lattice-Based Digital Signature Algorithm. Neither introduces value classes or null-restricted types.
The following features were finalized in JDK 25:
- JEP 513: Flexible Constructor Bodies.
- JEP 511: Module Import Declarations.
- JEP 512: Compact Source Files and Instance Main Methods.
- JEP 506: Scoped Values.
These final JDK 25 features do not require preview flags on JDK 26. Do not treat earlier preview examples as the final API contract.
Changes that deserve migration attention
Final-field mutation and removed APIs
JEP 500 introduces warnings for illegal final-field mutation through deep reflection by default, preparing for stricter enforcement in a future release. It does not make every reflective mutation fail immediately.
Exercise serialization, dependency injection, mocking, and persistence paths. If warnings appear, identify the responsible library and consult JEP 500 before applying a compatibility option. Prefer an updated library or a design that does not mutate final fields; do not broadly suppress diagnostics without an owner and removal plan.
JEP 504 removes the Applet API. Legacy code or dependencies referencing it need replacement or isolation, not a compiler flag that restores the removed API.
HTTP/3 and runtime performance
JEP 517 adds HTTP/3 support to java.net.http.HttpClient. Adoption still depends on server support, network conditions, and the protocol-selection behavior documented in the JEP. Validate proxies, UDP restrictions, fallback behavior, TLS configuration, and request telemetry before relying on it.
JEP 516 expands ahead-of-time object caching to work with any garbage collector. Evaluate startup and warmup using representative training workloads; follow the JEP’s workflow rather than assuming an existing cache is portable across runtime builds or deployments.
JEP 522 targets G1 throughput. Measure throughput, allocation rate, pause times, CPU, and memory under realistic load. ZGC is not the general default collector; G1 is the default on most server configurations. Preserve intentional collector choices while checking whether each existing flag remains supported.
Preview and incubator boundaries
PEM encodings, structured concurrency, lazy constants, and primitive patterns are previews in JDK 26. Their APIs or semantics may change in subsequent releases. Keep experiments isolated from stable service contracts and review the specific JEP before writing code.
Structured concurrency is still a sixth preview, not a finalized API. Examples from earlier previews may no longer compile or express the current lifecycle rules; use JEP 525 and the matching JDK documentation.
The Vector API is an incubator module, not a preview language feature. Using it requires opting into jdk.incubator.vector, typically with --add-modules jdk.incubator.vector during compilation and execution. Validate performance on the actual CPU architectures you deploy.
A practical migration workflow
1. Inventory the application and support matrix
Record the current JDK vendor and patch level, build runner, framework, libraries, agents, native integrations, container base image, and garbage-collector configuration.
Check authoritative compatibility information for your actual versions:
- Maven installation requirements and your compiler/test plugin documentation.
- Gradle Java compatibility matrix.
- Spring Boot system requirements, selecting documentation for your release.
- Quarkus documentation and the relevant platform release notes.
- JaCoCo change history and your monitoring/profiling agent release notes.
Check both the JDK that runs the build tool and the JDK used by its toolchain. A successful compiler invocation does not prove that test runners, bytecode instrumentation, annotation processors, or production agents support the same class-file version.
2. Establish a baseline, then change one variable
Capture existing functional results, startup time, latency percentiles, throughput, memory, GC behavior, and shutdown behavior. First run unchanged application code on the candidate runtime where compatibility allows; introduce new language features separately.
For an isolated JDK 26 compilation experiment:
# Use javac from JDK 26, or a compiler that supports release 26.
javac --release 26 -d out src/com/example/Main.java
java -cp out com.example.Main
--release 26 selects the Java 26 language, class-file target, and documented platform API surface. It does not make the output runnable on JDK 25 or older. Configure the equivalent release/toolchain settings in the project’s existing build system.
For JDK 26 preview code, use the matching JDK for both compilation and execution:
javac --enable-preview --release 26 -d out src/com/example/PreviewDemo.java
java --enable-preview -cp out com.example.PreviewDemo
Preview class files are tied to their release. Do not expect JDK 26 preview artifacts to run unchanged on JDK 27. Ensure test runners, application launchers, and container entrypoints receive the runtime flag too.
3. Audit dependencies and removed APIs
Run the tools from the candidate JDK against the built application and its runtime dependencies. Adapt these paths to your packaging:
jdeps --jdk-internals --class-path 'lib/*' app.jar
jdeps --multi-release 26 --recursive --class-path 'lib/*' app.jar
jdeprscan --release 26 --for-removal --class-path 'lib/*' app.jar
jdeps reports static dependencies, including internal JDK API usage. jdeprscan finds uses of deprecated Java SE APIs; it is not a complete detector for APIs already removed. Neither catches every reflective reference, dynamically loaded class, or JNI dependency.
Review release and migration notes alongside these reports. Run the project’s existing dependency vulnerability scan, examine transitive dependencies, and verify the chosen JDK distribution’s security advisories. Static API analysis is not a security scan.
4. Validate in CI and staging
- Pin the vendor, patch version, build toolchain, and container image; avoid an ambiguous moving tag.
- Keep the existing supported runtime in the CI matrix while evaluating the candidate.
- Run unit, integration, contract, and end-to-end suites, including agents and instrumentation.
- Exercise serialization, reflection, TLS, database drivers, native libraries, time zones, and locale-sensitive behavior.
- Test resource limits, load spikes, cancellation, shutdown, and recovery in production-like staging.
- Compare performance against the baseline with the same workload and collector configuration.
- Inspect startup logs for obsolete flags, final-field mutation warnings, and missing modules.
When moving directly to JDK 27, use its own release notes and matching tool settings. A JDK 26 assessment is useful context, not a substitute for validating the actual deployment target.
5. Roll out with a tested rollback
Use a canary or phased rollout with explicit error-rate, latency, and resource thresholds. Retain the previous supported image and application artifact, and rehearse rollback before expanding traffic.
Keep schema and protocol changes backward-compatible during the transition. If new bytecode targets a newer JDK, rollback must restore the compatible application artifact as well as the older runtime. Rebuild AOT caches for the selected deployment rather than assuming they survive a runtime change.
Migration checklist
- Choose JDK 25 LTS or JDK 27 with a verified maintenance policy.
- Reserve archived JDK 26 builds for isolated, non-production investigation.
- Verify build tools, frameworks, libraries, and agents against the selected JDK.
- Resolve removed API usage and investigate final-field mutation warnings.
- Keep preview/incubator experiments separate from the stable migration.
- Run static dependency analysis and the existing security scan.
- Validate CI, staging, performance, and runtime flags without blindly changing collectors.
- Rehearse rollback with compatible application artifacts and runtime images.
The safest enterprise upgrade is a supported runtime with measured compatibility, not adoption of every new feature. Use the corrected JDK 26 inventory to understand changes, then validate the maintained JDK you will actually deploy.