Java 8 → Java 17
Java 8 → 17 is the large jump. It crosses the module system, the removal of the javax.* Java EE modules, and strong encapsulation of JDK internals. Plan it as a project, not a flag flip.
Last verified · Updated May 22, 2026
Migrating from Java 8 to 17 is the large LTS jump. The risk is concentrated in three places: the module system (JPMS), the removed javax.* Java EE modules (JAXB/JAX-WS), and strong encapsulation of JDK internals. Most application logic compiles unchanged once those are handled.
Why this jump is large
Between 8 and 17 the JDK gained the module system, removed the bundled Java EE / CORBA modules, made G1 the default collector, and locked down reflective access to internals. None of these are about your business code — they are about how the platform is packaged and what it lets libraries reach into.
Key differences
- JPMS: strong encapsulation blocks reflective access to JDK internals (sun.misc.Unsafe, sun.*).
- Removed javax.* modules: JAXB, JAX-WS, javax.activation must become explicit dependencies.
- New language features available to adopt: records, sealed classes, switch expressions, text blocks, var.
- G1 is now the default garbage collector.
- Toolchain: set the compiler 'release' flag and bump Maven/Gradle plugins.
Files and patterns to inspect
- pom.xml / build.gradle: compiler source/target/release and plugin versions.
- Imports of javax.xml.bind (JAXB), javax.jws (JAX-WS), and javax.activation.
- Direct or reflective use of sun.misc.Unsafe and other sun.* / internal APIs.
- Lombok, ASM, ByteBuddy, and cglib versions (older bytecode libraries break on newer class files).
- Any existing --illegal-access or reflection-heavy framework configuration.
A clean compile is not proof of success. InaccessibleObjectException and missing javax.* classes typically surface at startup or first use. Exercise serialization and reflection-heavy paths before declaring the upgrade done.
Java LTS support matrix
| Version | Released | LTS | Support status |
|---|---|---|---|
| Java 8 | 2014-03-18 | Yes | Security-only |
| Java 11 | 2018-09-25 | Yes | Maintenance |
| Java 17 | 2021-09-14 | Yes | Active |
| Java 21 | 2023-09-19 | Yes | Current |
<!-- Maven: target Java 17 via the compiler release flag -->
<properties>
<maven.compiler.release>17</maven.compiler.release>
</properties>
<!-- Re-add a removed Java EE module as an explicit dependency -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.1</version>
</dependency>Scoped --add-opens
# Grant scoped reflective access only where strong encapsulation blocks it$ java --add-opens java.base/java.lang=ALL-UNNAMED -jar app.jarPre-migration checklist
- Green test suite on Java 8
- Dependencies audited for Java 17 support (especially Lombok and bytecode libraries)
- An inventory of javax.* Java EE usage and sun.* internal access
- A dedicated upgrade branch with the toolchain pinned
Related paths
Official sources
Backs the breaking-change and migration-step claims.
Backs the breaking-change and migration-step claims.
Copy-ready AI prompts
Structured prompts for an AI coding assistant. Inspect first, then execute incrementally, and keep a human in the review loop.
You are helping migrate a Java codebase from java-8 to java-17. Do not edit files yet. First inspect the repository and report: 1. The current source/target Java version in Maven (maven-compiler-plugin <release>/<source>/<target>) or Gradle (sourceCompatibility / toolchain languageVersion). 2. Usage of removed Java EE modules (javax.xml.bind/JAXB, javax.jws/JAX-WS, javax.activation) that must become explicit dependencies. 3. Reflective or direct access to JDK internals (sun.misc.Unsafe, sun.*, reflection into java.* internals) that strong encapsulation will block. 4. Build/toolchain versions: Maven, Gradle, and key plugins (compiler, surefire, shade) plus bytecode-manipulating libraries (Lombok, ASM, ByteBuddy, cglib) that must be bumped. 5. The build, test, and run commands. Return: a migration risk summary, the modules/classes most likely to break, a suggested migration order, the commands to run before editing, and any questions that need human confirmation.
Safety: Inspection only. The agent must not modify files in this step.
Works with Claude Code, Cursor, GitHub Copilot
Migrate this codebase from java-8 to java-17, one concern at a time. Work in this order and pause for review after each: (1) install the target JDK and point the build toolchain at it, (2) set the compiler 'release' flag to the target major, (3) add explicit dependencies for any removed javax.* modules surfaced during inspection, (4) bump Lombok and other bytecode-manipulating libraries to versions that support the target JDK, (5) add the minimum --add-opens/--add-exports flags only where strong encapsulation blocks required reflection, (6) fix remaining compile and test failures. After each step run the project's build and test commands and report results before continuing. Do not refactor unrelated code.
Safety: Apply changes incrementally and keep each step reviewable. Prefer fixing encapsulation violations over blanket --add-opens. Never bundle unrelated refactors.
Works with Claude Code, Cursor, GitHub Copilot
Test plan
Commands
java -version./mvnw -version./mvnw clean verify./gradlew build
Manual checks
- Startup: launch the app and confirm no InaccessibleObjectException or NoClassDefFoundError from removed javax.* modules.
- Serialization: exercise any JAXB/JAX-WS marshalling paths now backed by external dependencies.
- Reflection: verify frameworks doing reflective access (Jackson, Hibernate, Spring) start without illegal-access errors.
Regression risks
- Removed Java EE modules (JAXB/JAX-WS) failing at runtime rather than compile time.
- Older Lombok or ASM/ByteBuddy versions that cannot parse newer bytecode.
- Reflective access into JDK internals broken by strong encapsulation.
Acceptance criteria
- Clean build and full test suite pass on the target JDK.
- No InaccessibleObjectException or illegal-access warnings at startup.
- All bytecode-manipulating and serialization libraries resolve to target-JDK-compatible versions.
Frequently asked questions
Can I jump straight from Java 8 to 21?
You can, but it bundles the entire breaking-change surface into one step. Most teams find 8 → 17, then 17 → 21 easier to review and roll back, because the hard changes (modules, removed Java EE modules, encapsulation) are all in the 8 → 17 portion.
Do I need to add module-info.java?
Usually not. Applications can run on the classpath as 'unnamed modules' without becoming modular. You mainly deal with strong encapsulation — granting scoped --add-opens where a library reflects into JDK internals.