The Java platform is getting more powerful with every release. Migration from Java 11 to Java 17 will bring significant improvements in performance, security, and cloud-native capabilities of your Java-based workloads. With modern garbage collectors and new and updated APIs increasing security and facilitating code writing and maintenance, Java 17 is an essential upgrade for projects looking to stay competitive.
This guide provides a step-by-step approach to ensure a smooth transition and highlights common pitfalls to avoid.
Table of Contents
Key reasons to upgrade from Java 11 to Java 17
JDK 11 is a legacy LTS release. It is in maintenance mode meaning that only few improvements are backported to this branch. As a result, the performance of JDK-11 based workloads doesn’t meet the requirements for modern software.
But what exactly do we mean by improvements in Java 17? They are:
- Enhanced Garbage Collection: improved G1 GC, production-ready low-latency collectors ZGC and Shenandoah GC.
- Better security: Strong encapsulation of JDK internals (JEP 403) forbids using the internal components of the JDK, thus increasing the security of the Java platform and maintainability of the Java applications.
- New features: Java 17 includes
- The Foreign Function & Memory API (JEP 412) to interoperate with code and data outside of the Java runtime without the risks of JNI,
- Context-Specific Deserialization Filters (JEP 415) to configure the deserialization filters via a JVM-wide filter factory,
- Pattern matching for switch (JEP 406) to express data-oriented queries concisely and safely,
- Sealed classes (JEP 409) for better control over the code responsible for implementing the classes developers create.
- Better containerization: Optimizations for running Java in containers, including resource management improvements.
Upgrade Java version, dependencies, and tools
First of all, change the Java version for your project.
Download the binary with the latest release of Java 17 and follow the instructions to complete the installation. You can also use package managers (SDKMAN, Brew, etc.) or Linux repositories to install the JDK on your machine. For instance, to pull Liberica JDK 17 from a Yum repository, run
sudo yum update
sudo yum install bellsoft-java17
After that, change the JDK version in your IDE and build tools (Maven, Gradle).
If you use Docker images, update your Dockerfile as well. For instance, to move your application into a microcontainer with Liberica JDK and Alpaquita Linux, specify:
FROM bellsoft/liberica-runtime-container:jre-17-stream-musl
Note: you can use a glibc-based Alpaquita version if required for compatibility with the previous Linux distribution.
Now, update all tools, libraries, and third-party dependencies to versions that support JDK 17. The framework and its dependencies should also work with version 17. For example, here are the latest versions of common technologies used in Java development that support JDK 17:
- IntelliJ IDEA 2021.2.1
- Eclipse: 2021-09 (4.21)
- Maven: 3.8.1
- Gradle: 7.3
- Spring Boot: 2.5
- Lombok: 1.18
Naturally, the list goes on, but you get the idea.
After all the updates, compile and run your application and run the tests. Solve the remaining issues based on the error messages you see (if any). Some possible problems are described in the sections below.
Which Java distribution should you use?
The question arises if you find yourself in one of the following situations:
- You use Oracle Java and are dissatisfied with regular licensing changes or unwilling to pay for costly Java support according to the new Employee for Java SE Universal Subscription;
- You use Java distributions from several vendors and would like to unify the stack and lower the support expenses;
- You implement a free JDK build without support and would like to secure your project.
Firstly, if you run your workloads in Oracle Java, it is possible to migrate from Oracle to OpenJDK whose developers provide just as performant and secure runtimes. Secondly, you can use one runtime for all your platforms and purposes and receive affordable 24/7 services directly from experienced Java engineers. The key is to select a Java distribution with all features you need and cost-efficient support. Take a look at the Java alternatives overview with a comparison of the most popular Java distributions. Find out about their benefits, features, additional instruments, and supported system configurations, and make an informed decision.
Those of you who are looking for a reliable vendor, can download a comparison of commercial offerings provided by OpenJDK vendors, so that you have a clear understanding of the value you get for your money.
Java 11 to Java 17 comparison
The table below summarizes key differences between Java 11 and Java 17 in terms of performance-specific JVM features and support period.
Java 17 |
Java 11 | |
Garbage Collectors |
Improved G1 GC, Parallel GC, Serial GC |
G1 GC, Parallel GC, Serial GC, CMS GC |
Low-latency Garbage Collectors |
ZGC, Shenandoah GC* |
ZGC (Experimental), Shenandoah GC (since 11.0.9) |
CDS |
Dynamic AppCDS |
AppCDS |
Access to JDK internals |
Strong encapsulation (JEP 403) |
Possible with the --illegal-access flag |
Number of Intrinsics (x86_64) |
107 |
98 |
End of commercial support for Oracle Java SE |
2029 |
2026 |
End of free public updates for Oracle Java SE |
2022 |
2019 |
End of commercial support for Liberica JDK |
2030 |
2032 |
End of free public updates for Liberica JDK |
2030 |
2032 |
*Oracle Java doesn't include Shenandoah GC, but it is available with major OpenJDK distributions, including Liberica JDK.
For more details on the support terms consult Liberica JDK Support Roadmap.
Common migration issues
Migration from Java 11 to Java 17 can be associated with a few challenges related to the removed components and APIs and strong encapsulation of JDK internals. Here’s what you should consider.
Removed JVM options
Several JVM parameters were removed or deprecated up to Java 17. While obsolete or deprecated options make the program produce a warning without affecting its operation, the usage of removed ones will cause the JVM to exit with Error: Could not create the Java Virtual Machine
. The solution is to abstain from using the no longer valid parameters.
Discontinued components
The following tools have been removed from the JDK since Java 11, and if your code depends on them, it will require code modifications or migration to alternative solutions:
- The Applet API: Applets were removed as no modern browser supports them anymore. If your code uses applets, replace them with modern web technologies such as HTML5 or JavaScript-based solutions.
- The Security Manager: This API has been marked for removal. Consider adopting alternative sandboxing tools.
- The Remote Method Invocation (RMI) Activation: The RMI Activation has been removed, so you have to migrate to more robust distributed computing frameworks like gRPC.
- The Experimental Features AOT and Graal JIT: These features are now part of the standalone open-source GraalVM Project.
- The Concurrent Mark Sweep (CMS) Garbage Collector: The CMS GC has been deprecated and removed in favor of G1 GC. You can also try out low-latency garbage collectors ZGC or Shenandoah GC.
Managing removed APIs
There were a few APIs removed from the JDK since version 11. To identify affected areas in your code, utilize the jdeprscan
tool to search for usage of deprecated or eliminated APIs.
If the scan reveals dependencies on removed APIs, you can:
- Add related dependencies if the missing modules are now maintained as separate open-source libraries.
- Rewrite affected code using modern standard APIs.
Strong encapsulation of JDK internals
One of the JDK 17 features that may affect the migration process is strong encapsulation of JDK internals (JEP 403), whose goal is to make JDK more maintainable and secure. The reflective access to the low-level JDK APIs was restricted in Java 9, but versions 9–16 allowed the developers to use --illegal-access
option as a workaround. In Java 17, this parameter is no longer valid and the application will throw the java.lang.reflect.InaccessibleObjectException
.
To solve the issue, you should:
- Use standard APIs instead of internal ones.
- Update libraries to the latest versions that don’t access JDK internals. The
jdeps
tool with a--jdk-internals
option will help you pinpoint problematic libraries by listing class-level dependencies in the JDK internal APIs. - As a temporary workaround, you can use the
--add-exports
and--add-opens
options. But remember that using these tools compromises the security of your applications, so resort to them only in case of emergency and for a short term while you are rewriting the code.
GraalVM and Native Image compilation
If your application relied on the experimental AOT or Graal JIT features in Java 11, consider transitioning to GraalVM. GraalVM is a JDK and JVM written in Java that also offers Ahead-of-time compilation for fast startup times and reduced memory usage.
Several distributions of GraalVM are available: Oracle GraalVM and GraalVM Community edition with two downstream versions, Liberica Native Image Kit and Mandrel. Liberica NIK is recommended as a native-image compiler by Spring, so you can use it with your Spring applications to achieve faster startup and peak performance without warmup.
Recommendations for smooth migration
To ensure a smooth transition from Java 11 to Java 17:
- Test your application in a special set up testing environment with the updated JDK.
- Review and update all dependencies and build tools to versions compatible with JDK 17.
- Resolve any issues that arise after you have started your application.
- Identify dependence on removed APIs using
jdeprscan
and rewrite the code accordingly. - Identify libraries that depend on internal APIs using
jdeps
and update them or use alternative solutions.
With proper planning, you can efficiently address these challenges, allowing your project to leverage the performance, security, and modern features of Java 17.
How to stay on Java 11 and get all Java 17 perks?
If you are not ready for a full-fledged migration to Java 17, but want its performance improvements, consider Liberica JDK Performance Edition. This innovative solution that couples JDK 11 and JVM 17 enables you to:
- Boost performance. Achieve up to a 15% increase in startup times and lower latency.
- Preserve compatibility. Get the benefits of JVM 17 while maintaining your JDK 11-based infrastructure.
- Upgrade at your own pace. Upgrade less critical services first, leveraging the advantages of modern Java performance for critical services.