Sign in to Cloud

Migrating from Java 8 to Java 9

Step-by-step work can lead to the adoption of all or some of the features even without using modules.

By Trisha Gee

This article shows the steps you take to run Java 8 code and use some of the new features of Java 9 without migrating to modules. I principally examine what you need to do to get the code compiling and running.

Getting Started

First, download and install the latest version of JDK 9. At the time of this writing, it is still an Early Access release and can be found here (in this article, I’m using build 9-ea+166).

Until the impact of Java 9 on your system is understood, you probably don’t want it to be the default Java version. So, instead of updating $JAVA_HOME to point to the new installation, you might want to create a new environment variable, $JAVA9_HOME, instead. I’ll be using this approach throughout this article.

You should also look at this detailed migration guide to get a feel for what steps might be needed.

Before Jumping In

You can determine the amount of effort that might be required to migrate to Java 9 without even downloading or using it. There are several tools available in Java 8 that will give you appropriate hints.

Compiler warnings. First, of course, you can look at any compiler warnings, because some of those will tell you about potential problems (see Figure 1).

Figure 1. Example compiler warning about a potential problem

I’m using my IDE, IntelliJ IDEA, to compile the code and to show me the warnings, but what you see in the messages box in Figure 1 is the same as what you’d see using javac from the command line. Other IDEs, such as NetBeans and Eclipse, will have similar functionality. In Figure 1, you can see that the code has a field with a single underscore as a name. This single-underscore name has been removed as a legal identifier name in Java 9 as part of JDK Enhancement Proposal (JEP) 213. This is because underscores might be used in a later version of Java to make working with lambda expressions even easier. If you come across identifier names that consist of only a single underscore, you’ll need to rename them. Note that names containing underscores, for example _fieldName, are still valid; the problem is identifier names that contain only an underscore and nothing else.

Identify problematic dependencies with jdeps. One of the goals of this release, and surely the most famous Java 9 feature, is to allow the JDK developers to hide internal implementation details. In the past, developers were expected to follow guidelines to reduce the risk of depending on an unsupported class in the JDK; but it’s much better if a language, framework, or library can hide things that developers shouldn’t use. To make sure your code isn’t using internal APIs that will be hidden in Java 9, you can use a tool called jdeps.

Figure 2 shows where my compiled classes live in my project.

Figure 2. Location of compiled classes in the project

Many tutorials suggest you use jdeps with a JAR file, but you can also use it with your class files. For my application, I navigate to the location of my class files via the command line (Figure 2 shows that this is %PROJECT%\%MODULE%\build\classes) and from there, I run jdeps with the -jdkinternals flag. I’m using Windows, so my command line is the following, where main is the name of the directory containing my classes:

> %JAVA_HOME%\bin\jdeps -jdkinternals main

When I run this command, I get the output in Figure 3.

These messages indicate that my TwitterOAuth class is using the internal classes sun.misc.BASE64Encoder and sun.misc.Unsafe. The output suggests a replacement for the encoder, java.util.Base64, which was a new class in Java 8. unsafe is a special case, because there is no suitable replacement for all of its functionality yet.

JEP 260 talks about which internal APIs are going away and which will remain accessible. Java team member Mark Reinhold provided the following summary in an email to one of the principal JDK mailing lists to explain how each API will be handled by the Java team:

Figure 3. Output from running jdeps

If it has a supported replacement in JDK 8, then we will encapsulate it in JDK 9.

If it does not have a supported replacement in JDK 8, then we will not encapsulate it in JDK 9, so that it remains accessible to outside code.

If it has a supported replacement in JDK 9, then we will deprecate it in JDK 9 and encapsulate it, or possibly even remove it, in JDK 10.

Compiler warnings and jdeps can show you areas in your code that might be problematic in Java 9 and even suggest solutions. These problems can be fixed while you’re still running with an earlier version of Java (provided the suggested replacement classes are available in that version), and doing so will ease your transition to Java 9.

This article is excerpted from the July/August 2017 issue of Java Magazine. Continue to the full article to see what else you need to know to transition from Java 8 to Java 9.

Trisha Gee is a Java Champion with expertise in Java high-performance systems. She is a leader of the Seville Java User Group (SVQJUG) and dabbles in open source development. Gee is the IntelliJ IDEA developer advocate for JetBrains.