Java Compatibility Guide
Use this skill when writing, reviewing, or migrating Java applications, build
logic, launch scripts, runtime images, or operational tooling whose behavior
depends on recent JDK changes.
Prefer the project's declared toolchain and the runtime actually used in
production. Check build files, CI images, container bases, service definitions,
IDE launchers, and native packaging before recommending a migration.
How to use this skill
- Identify the compile JDK, runtime JDK, and whether preview features are
enabled.
- Search every launch surface for removed, deprecated, or experimental VM
options.
- Check source and bytecode for removed APIs before investigating secondary
failures.
- Rebuild preview-dependent code for the exact JDK release that will run it.
- Rebuild AOT caches when the application or any runtime input changes.
- Validate trust stores, providers, proxies, firewalls, and monitoring agents
as deployment inputs rather than treating the source tree as the whole
migration surface.
- Open the topic reference that matches the work; do not infer old behavior
from a similarly named replacement.
Reference index
| Reference |
Topics |
| Migration and removals |
Removed APIs, tools, launcher flags, platform support, deprecations |
| Language and APIs |
Module imports, compact source files, finalized APIs, previews |
| Runtime and performance |
Garbage collectors, object headers, AOT caches, virtual threads, JFR |
| Security and networking |
Native access, cryptography, trust stores, JNDI, HTTP/3 |
Breaking-change quick reference
Treat source, bytecode, and launch configuration separately
- Source compilation can fail after removal of Applet types.
- Existing bytecode can fail to link when it reaches a removed member such as
Thread.stop().
- A service can fail before application startup because the launcher rejects a
removed option.
- A running application can still be incorrect because a trust root, provider
algorithm, monitoring interface, or platform compatibility property changed.
High-risk removed surfaces
- Security Manager enablement is an error; legacy permission types are
migration-only surfaces and are themselves removal targets.
- Non-generational ZGC is gone. Configure ZGC without assuming the old mode
remains selectable.
java.net.Socket constructors no longer provide datagram sockets. Use
DatagramSocket or DatagramChannel.
- Applet APIs and
Thread.stop() are gone. Replace them at source and account
for linkage errors from old bytecode.
jrunscript is gone after first being deprecated for removal.
- The bundled experimental Graal JIT and 32-bit x86 JDK ports are not portable
migration assumptions.
Launcher and VM option audit
Search service units, shell scripts, container commands, build plugins, test
harnesses, and IDE metadata for:
- Removed launcher options:
-t, -tm, -Xfuture, -checksource, -cs, and
-noasyncgc.
- Removal-target aliases:
-verbosegc, -noclassgc, -verify,
-verifyremote, -ss, -ms, and -mx.
- Removal-target tuning options:
Xmaxjitcodesize,
AlwaysActAsServerClassMachine, NeverActAsServerClassMachine,
AggressiveHeap, and MaxRAM.
- Explicit
UseCompressedClassPointers tuning. The underlying feature remains;
the explicit option is the compatibility risk.
Move logging to unified logging and use supported long-form VM options.
Deprecation quick reference
Plan removal work for these categories before they become startup or linkage
failures:
ZipError, old Security Manager permission classes, and XML interchange in
JMX DescriptorSupport.
jstatd, jhsdb debugd, and the already removed jrunscript.
jdk.jsobject and legacy HotSpot locking modes.
- Linux
VFORK, java.locale.useOldISOCodes, and explicit compressed-class-
pointer tuning.
- 32-bit Linux x86 distributions and native artifacts.
Do not interpret deprecation of an option as removal of the feature it used to
tune. Verify the documented replacement or VM-selected behavior.
Preview and language quick reference
Preview discipline
- Compile and run preview code with
--enable-preview.
- Recompile preview-dependent code for every JDK release.
- Remove preview enablement only when no remaining source or dependency needs
it.
- Update source when a preview evolves; recompilation alone may not be enough.
- Keep module flags for incubating APIs such as the Vector API.
Module imports
A module import does not import subpackages and does not change module
readability. A type-import-on-demand declaration wins over a module import when
both expose the same simple name.
Do not generalize the broad reach of import module java.se; to arbitrary
modules; its reach follows java.se's transitive requirements.
Compact source files
IO is in java.lang, but its static methods are not implicitly imported.
Call IO.println(...) or add an explicit static import. Its I/O is backed by
System.in and System.out, not java.io.Console.
API status checks
- Class-file parsing, generation, and transformation are available through the
final Class-File API.
- Stream gatherers are final for custom intermediate stream operations.
- Module imports, compact source files and instance
main methods, flexible
constructor bodies, scoped values, and KDF are permanent features.
- Primitive patterns, structured concurrency, lazy constants, and PEM
encodings require release-specific preview checks.
Runtime quick reference
Garbage collection and object layout
- Generational ZGC is the only ZGC mode.
- Generational Shenandoah and compact object headers moved from experimental to
product status; do not retain the experimental unlock solely for them.
- Compact object headers use 64-bit headers on supported 64-bit platforms.
- AOT object caches are collector-neutral, but their other application and
runtime compatibility constraints still apply.
AOT cache safety
Treat an AOT cache as derived deployment output. Rebuild it when the
application, class path, module path, or JDK changes. A cache may reuse method
profiles, but it remains coupled to the inputs used to create it.
Threads and diagnostics
Most virtual threads blocked in synchronized code can unmount from carrier
threads, so do not diagnose every synchronized block as carrier pinning.
JFR CPU-time profiling, cooperative stack sampling, and method timing or
tracing are experimental diagnostics. Method tracing instruments code; scope
it narrowly.
Security and networking quick reference
- Treat native-access and
sun.misc.Unsafe warnings as migration work, not
harmless noise.
- Validate ML-KEM, ML-DSA, KDF, and PEM needs against API status for the
selected toolchain.
- Audit trust chains after default-root removals; do not assume a certificate
remains trusted because an older JDK trusted it.
- Audit provider algorithms when relying on SunPKCS11 PBE factories or older
DESede and PKCS1Padding requirements.
- For HTTP/3, test QUIC over UDP through network policy, proxies, firewalls,
fallback paths, certificate handling, and observability.
- Do not attempt to restore JNDI remote code downloading; it is permanently
disabled.
Symptom-driven lookup
| Symptom |
First checks |
Launcher exits before main |
Removed and deprecated launcher or VM options |
NoSuchMethodError around thread stopping |
Old bytecode calling removed Thread.stop() |
| Applet imports do not compile |
Removed java.applet or JApplet APIs |
| Final-field mutation warning |
Mutation grant scope and illegal-mutation policy |
| AOT cache behaves inconsistently |
Application, class path, module path, or JDK drift |
| TLS chain stops validating |
Removed default trust roots |
| Provider algorithm disappears |
SunPKCS11 and security-requirement changes |
| UDP path fails only with HTTP/3 |
QUIC reachability and fallback behavior |
| Monitoring agent loses data |
Removed PerfData, JMX properties, or private counters |
| Preview class will not load |
Matching compile/run flags and exact-release rebuild |
Review checklist
- Confirm compile and runtime JDKs.
- Identify every preview and incubator dependency.
- Scan all launcher surfaces, not only the main build file.
- Search source and packaged bytecode for removed APIs.
- Review GC, object-header, and AOT settings together.
- Review native access and final-field mutation grants for minimum scope.
- Validate trust roots and provider algorithms in a production-like image.
- Exercise HTTP/3 fallback and UDP network policy where applicable.
- Replace unsupported monitoring inputs with JFR, JMX, or supported
serviceability APIs.
- Record which caches, images, native artifacts, and installers must be rebuilt.
1---2name: java-knowledge-patch-23description: Java4license: MIT5---678# Java Compatibility Guide910Use this skill when writing, reviewing, or migrating Java applications, build11logic, launch scripts, runtime images, or operational tooling whose behavior12depends on recent JDK changes.1314Prefer the project's declared toolchain and the runtime actually used in15production. Check build files, CI images, container bases, service definitions,16IDE launchers, and native packaging before recommending a migration.1718## How to use this skill19201. Identify the compile JDK, runtime JDK, and whether preview features are21 enabled.222. Search every launch surface for removed, deprecated, or experimental VM23 options.243. Check source and bytecode for removed APIs before investigating secondary25 failures.264. Rebuild preview-dependent code for the exact JDK release that will run it.275. Rebuild AOT caches when the application or any runtime input changes.286. Validate trust stores, providers, proxies, firewalls, and monitoring agents29 as deployment inputs rather than treating the source tree as the whole30 migration surface.317. Open the topic reference that matches the work; do not infer old behavior32 from a similarly named replacement.3334## Reference index3536| Reference | Topics |37| --- | --- |38| [Migration and removals](references/migration-and-removals.md) | Removed APIs, tools, launcher flags, platform support, deprecations |39| [Language and APIs](references/language-and-apis.md) | Module imports, compact source files, finalized APIs, previews |40| [Runtime and performance](references/runtime-and-performance.md) | Garbage collectors, object headers, AOT caches, virtual threads, JFR |41| [Security and networking](references/security-and-networking.md) | Native access, cryptography, trust stores, JNDI, HTTP/3 |4243## Breaking-change quick reference4445### Treat source, bytecode, and launch configuration separately4647- Source compilation can fail after removal of Applet types.48- Existing bytecode can fail to link when it reaches a removed member such as49 `Thread.stop()`.50- A service can fail before application startup because the launcher rejects a51 removed option.52- A running application can still be incorrect because a trust root, provider53 algorithm, monitoring interface, or platform compatibility property changed.5455### High-risk removed surfaces5657- Security Manager enablement is an error; legacy permission types are58 migration-only surfaces and are themselves removal targets.59- Non-generational ZGC is gone. Configure ZGC without assuming the old mode60 remains selectable.61- `java.net.Socket` constructors no longer provide datagram sockets. Use62 `DatagramSocket` or `DatagramChannel`.63- Applet APIs and `Thread.stop()` are gone. Replace them at source and account64 for linkage errors from old bytecode.65- `jrunscript` is gone after first being deprecated for removal.66- The bundled experimental Graal JIT and 32-bit x86 JDK ports are not portable67 migration assumptions.6869### Launcher and VM option audit7071Search service units, shell scripts, container commands, build plugins, test72harnesses, and IDE metadata for:7374- Removed launcher options: `-t`, `-tm`, `-Xfuture`, `-checksource`, `-cs`, and75 `-noasyncgc`.76- Removal-target aliases: `-verbosegc`, `-noclassgc`, `-verify`,77 `-verifyremote`, `-ss`, `-ms`, and `-mx`.78- Removal-target tuning options: `Xmaxjitcodesize`,79 `AlwaysActAsServerClassMachine`, `NeverActAsServerClassMachine`,80 `AggressiveHeap`, and `MaxRAM`.81- Explicit `UseCompressedClassPointers` tuning. The underlying feature remains;82 the explicit option is the compatibility risk.8384Move logging to unified logging and use supported long-form VM options.8586## Deprecation quick reference8788Plan removal work for these categories before they become startup or linkage89failures:9091- `ZipError`, old Security Manager permission classes, and XML interchange in92 JMX `DescriptorSupport`.93- `jstatd`, `jhsdb debugd`, and the already removed `jrunscript`.94- `jdk.jsobject` and legacy HotSpot locking modes.95- Linux `VFORK`, `java.locale.useOldISOCodes`, and explicit compressed-class-96 pointer tuning.97- 32-bit Linux x86 distributions and native artifacts.9899Do not interpret deprecation of an option as removal of the feature it used to100tune. Verify the documented replacement or VM-selected behavior.101102## Preview and language quick reference103104### Preview discipline105106- Compile and run preview code with `--enable-preview`.107- Recompile preview-dependent code for every JDK release.108- Remove preview enablement only when no remaining source or dependency needs109 it.110- Update source when a preview evolves; recompilation alone may not be enough.111- Keep module flags for incubating APIs such as the Vector API.112113### Module imports114115A module import does not import subpackages and does not change module116readability. A type-import-on-demand declaration wins over a module import when117both expose the same simple name.118119Do not generalize the broad reach of `import module java.se;` to arbitrary120modules; its reach follows `java.se`'s transitive requirements.121122### Compact source files123124`IO` is in `java.lang`, but its static methods are not implicitly imported.125Call `IO.println(...)` or add an explicit static import. Its I/O is backed by126`System.in` and `System.out`, not `java.io.Console`.127128### API status checks129130- Class-file parsing, generation, and transformation are available through the131 final Class-File API.132- Stream gatherers are final for custom intermediate stream operations.133- Module imports, compact source files and instance `main` methods, flexible134 constructor bodies, scoped values, and KDF are permanent features.135- Primitive patterns, structured concurrency, lazy constants, and PEM136 encodings require release-specific preview checks.137138## Runtime quick reference139140### Garbage collection and object layout141142- Generational ZGC is the only ZGC mode.143- Generational Shenandoah and compact object headers moved from experimental to144 product status; do not retain the experimental unlock solely for them.145- Compact object headers use 64-bit headers on supported 64-bit platforms.146- AOT object caches are collector-neutral, but their other application and147 runtime compatibility constraints still apply.148149### AOT cache safety150151Treat an AOT cache as derived deployment output. Rebuild it when the152application, class path, module path, or JDK changes. A cache may reuse method153profiles, but it remains coupled to the inputs used to create it.154155### Threads and diagnostics156157Most virtual threads blocked in `synchronized` code can unmount from carrier158threads, so do not diagnose every synchronized block as carrier pinning.159160JFR CPU-time profiling, cooperative stack sampling, and method timing or161tracing are experimental diagnostics. Method tracing instruments code; scope162it narrowly.163164## Security and networking quick reference165166- Treat native-access and `sun.misc.Unsafe` warnings as migration work, not167 harmless noise.168- Validate ML-KEM, ML-DSA, KDF, and PEM needs against API status for the169 selected toolchain.170- Audit trust chains after default-root removals; do not assume a certificate171 remains trusted because an older JDK trusted it.172- Audit provider algorithms when relying on SunPKCS11 PBE factories or older173 DESede and PKCS1Padding requirements.174- For HTTP/3, test QUIC over UDP through network policy, proxies, firewalls,175 fallback paths, certificate handling, and observability.176- Do not attempt to restore JNDI remote code downloading; it is permanently177 disabled.178179## Symptom-driven lookup180181| Symptom | First checks |182| --- | --- |183| Launcher exits before `main` | Removed and deprecated launcher or VM options |184| `NoSuchMethodError` around thread stopping | Old bytecode calling removed `Thread.stop()` |185| Applet imports do not compile | Removed `java.applet` or `JApplet` APIs |186| Final-field mutation warning | Mutation grant scope and illegal-mutation policy |187| AOT cache behaves inconsistently | Application, class path, module path, or JDK drift |188| TLS chain stops validating | Removed default trust roots |189| Provider algorithm disappears | SunPKCS11 and security-requirement changes |190| UDP path fails only with HTTP/3 | QUIC reachability and fallback behavior |191| Monitoring agent loses data | Removed PerfData, JMX properties, or private counters |192| Preview class will not load | Matching compile/run flags and exact-release rebuild |193194## Review checklist195196- Confirm compile and runtime JDKs.197- Identify every preview and incubator dependency.198- Scan all launcher surfaces, not only the main build file.199- Search source and packaged bytecode for removed APIs.200- Review GC, object-header, and AOT settings together.201- Review native access and final-field mutation grants for minimum scope.202- Validate trust roots and provider algorithms in a production-like image.203- Exercise HTTP/3 fallback and UDP network policy where applicable.204- Replace unsupported monitoring inputs with JFR, JMX, or supported205 serviceability APIs.206- Record which caches, images, native artifacts, and installers must be rebuilt.