Authored by Abhishek Shukla, Sr. Software Engineer
Java 8 is at its end-of-life. Public updates have been discontinued as of January 2019, making it even more important to move on to the next long-term-support version, Java 11.
Unlike the previous versions, the migration to the newer releases have some challenges. But fear not, this blog will address the disruptive features of the newer Java versions and the challenges in migration.
JDK, Releases and Licenses: Java has been going through a lot of changes now and there is a new release cadence to Java.
With Java 11, Oracle JDK will be released under a commercial license and developers can use OracleJDK for free for development but not for production.
Oracle is also releasing Oracle OpenJDK which can be used for free, though the user will have to follow their 6-month release cycle. This means one can use it for free provided they update every 6 months. This will include LTS (Long Term Support) versions of Java.
Apart from the JDK builds there would be OpenJDK builds released by other providers such as AdoptOpenJDK, Azul, IBM, Red Hat, etc. These builds are implementations of Java Specification, having passed the Java Technology Certification Kit and can be used freely.
Now let’s address the elephant in the room and talk migration from Java 8 to 11.
To make the migration less troublesome, Java 11 supports both classpath and module-path based configuration. Hence it is not required to modularize the project completely while migrating to Java 11. One can follow an incremental approach and migrate the project in phases.
Following these steps will help:
Update all your IDEs, build tools and application dependencies to use the latest version. Updating the dependencies is not required at this time, but it will save a lot of trouble if the used version does not support Java 11.
Following are some of the tools and the recommended version for Java 11.
Compile the application:
Compiling the application on Java 11 can result in raising a few issues. Here is a pre-emptive look at some of those issues and how they can be fixed.
Unofficial access to Internal APIs:
Many developers have been using classes from packages which were intended for internal for the JDK. And as Java core libraries are already modularized, with strong encapsulation in place, these packages are no longer available for “public” use. One example is the Base64Encoder in the package “sun.misc”.
If your application is using any of these internal packages, the compiler would flag these as errors :
JDeps is a tool provided by the JDK that can be used to scan the code and dependent jar for this unofficial access and other issues.
Using jdeps on Guava (version 18) library, we can see the unofficial access to internal JDK packages by older versions of Mockito and Guava.
Removal of Java EE modules:
The following modules had been marked as deprecated in JDK 9 and have been removed in Java 11.
On compiling the application on Java 11, if the code was using one of the above-mentioned functionalities, it would get compilation issues as follows:
These modules have been removed from JDK and are now maintained separately and need to be mentioned as dependencies for the application. The issue in the above-mentioned example can be resolved by adding this dependency for JAXB:
Two or more JARs can have the same package name. This is typically the case where one JAR has the interface of the library and other JARs have different implementations. They use the same package name to access the package private classes of each other. This is called split packages.
With Java 9, the split packages in modules are not allowed. Two modules cannot have the same package names, internal or external.
However, one can have split packages in the Unnamed module, that is, multiple JARs mentioned on the class path can still have split packages. But problem arises when a module (with module-info) has the same package name as one of the JARs on the classpath. In this case, following errors are observed:
Renaming the package in one of the module/JAR would resolve the issue. If renaming is not possible, we would have to look for alternatives of the conflicting module/JAR.
Modularize your application:
It is not really required to modularize the application for migration. Java 11 supports both classpath and module path, hence all the dependencies can still be mentioned on the classpath. Java internally groups the JARs on the classpath as one module, called the “Unnamed module”.
And if you are looking for a quick migration, you do not need to modularize the application completely.
Following points need to be considered while creating the module-info files:
To summarize, Java 8 is reaching EOL and it is time to move on to the next LTS version of Java, that is Java 11. With Java 11, Oracle JDK is being released with a commercial license and will not be available for free use. There are OpenJDK builds released by other providers, that can be used for free.
Migrating to Java 11 does offer some challenges
In conclusion, we can say that there few challenges to migrating to the Java 11 can be easily overcome. For quicker migration, command line directives can be used to allow access to JDK internal APIs, but this is temporary and is not recommended.
For more information or consultation, please contact here.