6 Preparing For Migration

Tip:

Evaluate the Effort of Migration with Java Migration Analysis

Oracle offers Java SE Subscribers and Oracle Cloud Infrastructure (OCI) users the Java Migration Analysis feature in the Java Management Service. This feature performs a comprehensive analysis of the effort involved in migrating to a new JDK version. It generates detailed reports highlighting the effort required and areas needing modification for migrating from an older JDK version to a newer one. During the migration process, you can utilize the analysis reports from Migration Analysis to identify classes and APIs that require changes. The reports specify line numbers in the source code where modifications are needed and highlight both mandatory and recommended changes.

The following sections will help you successfully migrate your application:

Download the Latest JDK

Download and install the latest JDK release from Java SE Downloads.

Run Your Program Before Recompiling

Try running your application on the latest JDK release (JDK 22). Most code and libraries should work on JDK 22 without any changes, but there may be some libraries that need to be upgraded.

Note:

Migrating is an iterative process. You’ll probably find it best to try running your program (this task) first, then complete these three tasks in parallel:

When you run your application, look for warnings from the JVM about obsolete VM options. If the VM fails to start, then look for Removed GC Options.

If your application starts successfully, look carefully at your tests and ensure that the behavior is the same as on the JDK version you have been using. For example, a few early adopters have noticed that their dates and currencies are formatted differently. See Migrate Away From the COMPAT Locale Data Provider.

To make your code work on the latest JDK release, understand the new features and changes in each of the JDK release.

Even if your program appears to run successfully, you should complete the rest of the steps in this guide and review the list of issues.

Update Third-Party Libraries

For every tool and third-party library that you use, you may need to have an updated version that supports the latest JDK release.

Check the websites for your third-party libraries and your tool vendors for a version of each library or tool that’s designed to work on the latest JDK. If one exists, then download and install the new version.

If you use Maven or Gradle to build your application, then make sure to upgrade to a recent version that supports the latest JDK version.

If you use an IDE to develop your applications, then it might help in migrating the existing code. The NetBeans, Eclipse, and IntelliJ IDEs all have versions available that include support for the latest JDK.

You can see the status of the testing of many Free Open Source Software (FOSS)  projects with OpenJDK builds at Quality Outreach on the OpenJDK wiki.

Compile Your Application if Needed

Compiling your code with the latest JDK compiler will ease migration to future releases since the code may depend on APIs and features, which have been identified as problematic. However, it is not strictly necessary.

If you need to compile your code with JDK 11 and later compilers, then take note of the following:

  • Use the new --release flag instead of the -source and -target options. See javac in Java Development Kit Tool Specifications.

    The supported values of --release are the current Java SE release and a limited number of previous releases, detailed in the command-line help.

    The javac can recognize and process class files of all previous JDKs, going all the way back to JDK 1.0.2 class files.

    See JEP 182: Policy for Retiring javac -source and -target Options.

  • If you use the -source and -target options with javac, then check the values that you use.

    The supported -source/-target values are 22 (the default) till 9. The value 8 is deprecated and causes a warning.

    In JDK 8, -source and -target values of 1.7/7 and earlier were deprecated, and caused a warning. In JDK 9 and above, those values cause an error.

    >javac -source 7 -target 7 Sample.java 
    warning: [options] bootstrap class path is not set in conjunction with -source 7
      not setting the bootstrap class path may lead to class files that cannot run on JDK 8
        --release 7 is recommended instead of -source 7 -target 7 because it sets the bootstrap class path automatically
    error: Source option 7 is no longer supported. Use 8 or later.
    error: Target option 7 is no longer supported. Use 8 or later.

    Note:

    When using --release, you cannot also use the --source/-source or --target/ -target options.
  • If you use the underscore character ("_") as a one-character identifier in source code, then your code won’t compile in JDK 11 and later releases. It generates a warning in JDK 8, and an error, starting from JDK 9.

    As an example:

    static Object _ = new Object();

    This code generates the following error message from the compiler:

    MyClass.java:2: error: as of release 9, '_' is a keyword, and may not be used as a legal identifier.
    
  • Critical internal JDK APIs such as sun.misc.Unsafe are still accessible in JDK 11 and later, but most of the JDK’s internal APIs are not accessible at compile time. You may get compilation errors that indicate that your application or its libraries are dependent on internal APIs.

    To identify the dependencies, run the Java Dependency Analysis tool. See Run jdeps on Your Code. If possible, update your code to use the supported replacement APIs.

    You may use the --add-exports and --add-opens options as a temporary workaround to compile source code with references to JDK internal classes. See JEP 261: Module System and Strong Encapsulation in the JDK for more information about these options.

  • You may see more deprecation warnings than previously.

Run jdeps on Your Code

Run the jdeps tool on your application to see what packages and classes your applications and libraries depend on. If you use internal APIs, then jdeps may suggest replacements to help you to update your code.

To look for dependencies on internal JDK APIs, run jdeps with the -jdkinternals option. For example, if you run jdeps on a class that calls sun.misc.BASE64Encoder, you’ll see:

>jdeps -jdkinternals Sample.class
Sample.class -> JDK removed internal API
   Sample  -> sun.misc.BASE64Encoder  JDK internal API (JDK removed internal API)

Warning: JDK internal APIs are unsupported and private to JDK implementation that are
subject to be removed or changed incompatibly and could break your application.
Please modify your code to eliminate dependency on any JDK internal APIs.
For the most recent update on JDK internal API replacements, please check:
https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool

JDK Internal API                         Suggested Replacement
----------------                         ---------------------
sun.misc.BASE64Encoder                   Use java.util.Base64 @since 1.8

If you use Maven, there’s a jdeps plugin available.

For jdeps syntax, see jdeps in the Java Development Kit Tool Specifications.

Keep in mind that jdeps is a static analysis tool, and static analysis of code might not provide a complete list of dependencies. If the code uses reflection to call an internal API, then jdeps doesn’t warn you.