Hard java java-21

How would you migrate an application from Java 8 to Java 21?

The 30 second answer

I'd upgrade build tools and libraries first, because old bytecode tools and frameworks are the usual blockers. Then I scan for use of internal JDK APIs, add back Java EE pieces like JAXB that were removed in Java 11, and fix reflection that strong encapsulation now blocks. I check removed JVM flags, run the full test suite, roll out gradually, and only then adopt new features.

  1. Tooling and libraries first. Maven or Gradle plugins, Lombok, Mockito, ByteBuddy, ASM and your framework versions must support Java 21.
  2. Find internal API use: jdeps --jdk-internals app.jar lists dependencies on internal JDK classes and suggests replacements.
  3. Removed modules. Java 11 removed the Java EE and CORBA modules (JEP 320), so JAXB, JAX-WS and the common annotations must come in as normal dependencies.
  4. Strong encapsulation. Since Java 17 (JEP 403) deep reflection into JDK internals fails by default. Upgrade the library; use --add-opens only as a temporary workaround.
  5. JVM flags. Old GC logging flags like -XX:+PrintGCDetails are replaced by -Xlog; the CMS collector was removed in Java 14 (JEP 363); some removed flags stop the JVM from starting.
  6. Test and roll out. Full test suite and performance tests, then a canary deployment.
  7. Adopt new features only after it runs: records, pattern matching, virtual threads.

Spring Boot 3 requires Java 17 or later and moves from javax.* to jakarta.* packages. [Opinion] So a Java 8 Spring Boot 2 app is usually a Java and framework migration together; doing it in steps (for example Java 17 on Spring Boot 2.7 first, then Spring Boot 3 and Java 21) reduces risk.

Sources: Oracle JDK 21 Migration Guide, JEP 320: Remove the Java EE and CORBA Modules, JEP 403: Strongly Encapsulate JDK Internals, JEP 363: Remove the CMS Garbage Collector, jdeps, Spring Boot system requirements

Sources (0)
See inline citations in the answer above.