Oracle JDK 9 Migration Guide
Release 9
E82965-05
October 2017
The purpose of this guide is to help you identify potential issues and give you suggestions on how to proceed as you migrate your existing Java application to JDK 9.
Every new Java SE release introduces some binary, source, and behavioral incompatibilities with previous releases. The modularization of the Java SE Platform brings many benefits, but also many changes. Code that uses only official Java SE Platform APIs and supported JDK-specific APIs should continue to work without change. Code that uses JDK-internal APIs should continue to run but should be migrated to use external APIs.
To migrate your application, start by following the steps listed inPrepare for Migration.
Finally, when your application is running successfully on JDK 9, reviewLooking Forward, which will help you avoid problems with future releases.
This guide focuses on changes required to make your code run on JDK 9. For a comprehensive list of all of the new features of JDK 9, seeJava Platform, Standard Edition What's New in JDK 9 For detailed information about the changes mentioned in this guide, refer toJDK 9 Release Notes.
Try running your application on JDK 9. Most code and libraries should work on JDK 9 without any changes, but there may be some libraries that need to be upgraded.
Note:
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 options, because some VM flags that were deprecated in JDK 8 have been removed in JDK 9. SeeRemoved GC Options.
If your application starts successfully, look carefully at your tests and ensure that the behavior is the same as on JDK 8. For example, a few early adopters have noticed that their dates and currencies are formatted differently. SeeUse CLDR Locale Data by Default.
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.
For every tool and third-party library that you use, you may need to have an updated version that supports JDK 9.
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 JDK 9. 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 more recent version that supports JDK 9.
If you use an IDE to develop your applications, then it can help to migrate existing code. The NetBeans, Eclipse, and IntelliJ IDEs all have versions available that include JDK 9 support.
You can see the status of the testing of many Free Open Source Software (FOSS) projects with OpenJDK builds atQuality Outreach on the OpenJDK wiki.
Compiling your code with the JDK 9 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 the JDK 9 compiler then take note of the following:
If you use the underscore character ("_") as a one-character identifier in source code, then your code won’t compile in JDK 9. Its use generates a warning in JDK 8, and an error in 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.
If you use the-source
and-target
options withjavac
, then check the values that you use. In JDK 9,javac
uses a "one plus three back" policy of supporting-source
and-target
options.
The supported-source/-target
values are 9 (the default), 8, 7, and 6 (6 is deprecated, and a warning is displayed when this value is used).
In JDK 8,-source
and-target
values of 1.5/5 and earlier were deprecated and caused a warning to be generated. In JDK 9, those values cause an error.
>javac -source 5 -target 5 Sample.javawarning: [options] bootstrap class path not set in conjunction with -source 1.5 error: Source option 1.5 is no longer supported. Use 1.6 or later. error: Target option 1.5 is no longer supported. Use 1.6 or later.
If possible, use the new--release
flag instead of the-source
and-target
options. The--release N
flag is conceptually a macro for:
-source N -target N -bootclasspath $PATH_TO_rt.jar_FOR_RELEASE_N
The valid arguments for the--release
flag follow the same policy as for-source
and-target
, one plus three back.
javac
can recognize and process class files of all previous JDKs, going all the way back to JDK 1.0.2 class files.
SeeJEP 182: Policy for Retiring javac -source and -target Options.
Critical internal JDK APIs such assun.misc.Unsafe are still accessible in JDK 9, 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. SeeRun jdeps on Your Code. If possible, update your code to use the supported replacement APIs.
You may use the--add-exports
option as a temporary workaround to compile source code with references to JDK internal classes.
You may see more deprecation warnings than previously. If you see deprecation with removal warnings, then you should address those to avoid future problems.
A number of small changes have been made tojavac
to align it with the Java SE 9 Language Specification.
You may encounter some source compatibility issues when recompiling.
TheJDK 9 Release Notes contains details of changes to thejavac
compiler and source compatibility issues in JDK 9.
Run thejdeps
tool on your application to see what packages and classes your applications and libraries depend on. If you use internal APIs, thenjdeps
may suggest replacements to help you to update your code.
To look for dependencies on internal JDK APIs, runjdeps
with the-jdkinternals
option. For example, if you runjdeps
on a class that callssun.misc.BASE64Encoder
, you’ll see:
>jdeps -jdkinternals Sample.classSample.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 aresubject 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+ToolJDK Internal API Suggested Replacement---------------- ---------------------sun.misc.BASE64Encoder Use java.util.Base64 @since 1.8
If you use Maven, there’s ajdeps
plugin available.
Forjdeps
syntax, seejdeps
in theJava Platform, Standard Edition Tools Reference.
Keep in mind thatjdeps
is a static analysis tool, and static analysis of code doesn’t tell you everything. If the code uses reflection to call an internal API, thenjdeps
doesn’t warn you.
JDK 9 provides a new simplified version-string format. If your code relies on the version-string format to distinguish major, minor, security, and patch update releases, then you may need to update it.
The format of the new version-string is:
$MAJOR.$MINOR.$SECURITY.$PATCH
For example, under the old scheme, the Java9u5
security release would have the version string1.9.0_5-b20
.
Under the new scheme, the short version of the same release is9.0.1
, and the long version is9.0.1+20
.
This change affectsjava -version and related system properties, such asjava.runtime.version,java.vm.version,java.specification.version, andjava.vm.specification.version.
A simple Java API to parse, validate, and compare version strings has been added. Seejava.lang.Runtime.Version.
SeeVersion String Format inJava Platform, Standard Edition Installation Guide, andJEP 223: New Version-String Scheme.
Some tools and libraries use reflection to access parts of the JDK that are meant for internal use only. This illegal reflective access will be disabled in a future release of the JDK. In JDK 9, it is permitted by default and a warning is issued.
For example, here is the warning issued when starting Jython:
>java -jar jython-standalone-2.7.0.jarWARNING: An illegal reflective access operation has occurredWARNING: Illegal reflective access by jnr.posix.JavaLibCHelper (file:/C:/Jython/jython2.7.0/jython-standalone-2.7.0.jar) to method sun.nio.ch.SelChImpl.getFD()WARNING: Please consider reporting this to the maintainers of jnr.posix.JavaLibCHelperWARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operationsWARNING: All illegal access operations will be denied in a future releaseJython 2.7.0 (default:9987c746f838, Apr 29 2015, 02:25:11)
If you see a warning like this, contact the maintainers of the tool or library. The second line of the warning names the exact JAR file whose code used reflection to access an internal part of the JDK.
By default, a maximum of one warning about reflective access is issued in the lifetime of the process started by thejava
launcher. The exact timing of the warning depends on the behavior of tools and libraries performing reflective–access operations. The warning may appear early in the lifetime of the process, or a long time after startup.
You can disable the warning message on a library-by-library basis by using the--add-opens
command line flag. For example, you can start Jython in the following way:
>java --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED -jar jython-standalone-2.7.0.jarJython 2.7.0 (default:9987c746f838, Apr 29 2015, 02:25:11)
This time, the warning is not issued because thejava
invocation explicitly acknowledges the reflective access. As you can see, you may need to specify multiple--add-opens
flags to cover all of the reflective access operations that are attempted by libraries on the class path.
To better understand the behavior of tools and libraries, you can use the--illegal-access=warn
command line flag. This flag causes a warning message to be issued for every illegal reflective-access operation. In addition, you can obtain detailed information about illegal reflective-access operations, including stack traces, by setting--illegal-access=debug
.
If you have updated libraries, or when you get them, then you can experiment with using the--illegal-access=deny
command line flag. It disables all reflective-access operations except for those enabled by other command-line options, such as--add-opens
. This will be the default mode in a future release.
--illegal-access=deny
, or, as already mentioned, to suppress warnings.--add-exports
runtime option. You can also use--add-exports
at compile time to access internal APIs.--add-opens
option.If you want to suppress all reflective access warnings, then use the--add-exports
and--add-opens
options where needed.
If you must use an internal API that has been made inaccessible by default, then you can break encapsulation using the--add-exports
command-line option.
--add-exports
option is:--add-exports <source-module>/<package>=<target-module>(,<target-module>)*where
<source-module>
and<target-module>
are module names and<package>
is the name of a package.The--add-exports
option allows code in the target module to access types in the named package of the source module if the target module reads the source module.
<target-module>
isALL-UNNAMED
, then the source package is exported to all unnamed modules, whether they exist initially or are created later on. For example:--add-exports java.management/sun.management=ALL-UNNAMEDThis example allows code in all unnamed modules (code on the class path) to access the public members of public types in
java.management/sun.management
. If the code on the class path attempts to dodeep reflection to access nonpublic members, then the code fails.oldApp
that runs on the classpath must use the unexportedcom.sun.jmx.remote.internal
package of thejava.management
module, then the access that it requires can be granted in this way:--add-exports java.management/com.sun.jmx.remote.internal=ALL-UNNAMED
Add-Exports:java.management/sun.management
Use the--add-exports
option carefully. You can use it to gain access to an internal API of a library module, or even of the JDK itself, but you do so at your own risk. If that internal API changes or is removed, then your library or application fails.
See alsoJEP 261.
If you have to allow code on the class path to dodeep reflection to access nonpublic members, then use the--add-opens
runtime option.
Some libraries do deep reflection, meaningsetAccessible(true)
, so they can access all members, including private ones. You can grant this access using the--add-opens
option on thejava
command line. No warning messages are generated as a result of using this option.
If--illegal-access=deny
, and you seeIllegalAccessException
orInaccessibleObjectException
messages at runtime, you could use the--add-opens
runtime option, basing the arguments upon the information shown in the exception message.
--add-opens
is:--add-opens module/package=target-module(,target-module)*This option allows
<module>
to open<package>
to<target-module>
, regardless of the module declaration.<target-module>
isALL-UNNAMED
, then the source package is exported to all unnamed modules, whether they exist initially or are created later on. For example:--add-opens java.management/sun.management=ALL-UNNAMEDThis example allows all of the code on the class path to access nonpublic members of public types in the
java.management/sun.management
package.Note:
If you are using the JNI Invocation API, including, for example, a Java Web Start JNLP file, you must include an equals sign between--add-opens
and its value.<j2se version="9" java-vm-args="--add-opens=module/package=ALL-UNNAMED" />
That equals sign is optional on the command line.
After you install JDK 9, if you look at the file system, you’ll notice that the directory layout is different from that of previous releases.
Prior releases produced two types of runtime images: the JRE, which was a complete implementation of the Java SE Platform, and the JDK, which included the entire JRE in ajre/
directory, plus development tools and libraries.
In JDK 9, the JDK and JRE are two types of modular runtime images, where each contains the following directories:
bin
— contains binary executables.
conf
— contains.properties
,.policy
, and other kinds of files intended to be edited by developers, deployers, and end users. These files were formerly found in thelib
directory or its subdirectories.
lib
— contains dynamically linked libraries and the complete internal implementation of the JDK.
There are still separate JDK and JRE downloads, but each has the same directory structure. The JDK image contains the extra tools and libraries that have historically been found in the JDK. There are nojdk/
versusjre/
wrapper directories, and binaries (such as thejava
command) aren’t duplicated.
SeeJEP 220: Modular Run-Time Images andInstalled Directory Structure of JDK and JRE inJava Platform, Standard Edition Installation Guide.
JDK 9 maintains the hierarchy of class loaders that existed since the 1.2 release. However, the following changes have been made to implement the module system:
The application class loader is no longer an instance ofURLClassLoader but, rather, of an internal class. It is the default loader for classes in modules that are neither Java SE nor JDK modules.
The extension class loader has been renamed; it is now the platform class loader. All classes in the Java SE Platform are guaranteed to be visible through the platform class loader. In addition, the classes in modules that are standardized under the Java Community Process but not part of the Java SE Platform are guaranteed to be visible through the platform class loader.
Just because a class is visible through the platform class loader does not mean the class is actually defined by the platform class loader. Some classes in the Java SE Platform are defined by the platform class loader while others are defined by the bootstrap class loader. Applications should not depend on which class loader defines which platform class.
The changes in JDK 9 may impact code that creates class loaders withnull
(that is, the bootstrap class loader) as the parent class loader and assumes that all platform classes are visible to the parent. Such code may need to be changed to use the platform class loader as the parent (seeClassLoader.getPlatformClassLoader).
The platform class loader is not an instance ofURLClassLoader, but, rather, of an internal class.
The bootstrap class loader is still built-in to the Java Virtual Machine and represented bynull
in theClassLoader API. It defines the classes in a handful of critical modules, such asjava.base. As a result, it defines far fewer classes than in JDK 8, so applications that are deployed with-Xbootclasspath/a
or that create class loaders withnull
as the parent may need to change as described previously.
Class and resource files previously stored inlib/rt.jar
,lib/tools.jar
,lib/dt.jar
and various other internal JAR files are stored in a more efficient format in implementation-specific files in thelib
directory.
The removal ofrt.jar
and similar files leads to issues in these areas:
In JDK 9,ClassLoader.getSystemResource doesn’t return a URL pointing to a JAR file (because there are no JAR files). Instead, it returns ajrt
URL, which names the modules, classes, and resources stored in a runtime image without revealing the internal structure or format of the image.
For example:
ClassLoader.getSystemResource("java/lang/Class.class");
When run on JDK 8, this method returns a JAR URL of the form:
jar:file:/usr/local/jdk8/jre/lib/rt.jar!/java/lang/Class.class
which embeds a file URL to name the actual JAR file within the runtime image.
jrt:/java.base/java/lang/Class.class
Thejava.security.CodeSource API and security policy files use URLs to name the locations of code bases that are to be granted specific permissions. SeePolicy File Syntax inJava Platform, Standard Edition Security Developer's Guide. Components of the runtime system that require specific permissions are currently identified in theconf/security/java.policy
file by using file URLs.
IDEs and other development tools require the ability to enumerate the class and resource files stored in a runtime image, and to read their contents directly by opening and readingrt.jar
and similar files. This isn’t possible with a modular image.
In previous releases, the extension mechanism made it possible for the runtime environment to find and load extension classes without specifically naming them on the class path. In JDK 9, if you need to use the extension classes, ensure that the JAR files are on the class path.
Thejavac
compiler andjava
launcher will exit if thejava.ext.dirs
system property is set, or if thelib/ext
directory exists. To additionally check the platform-specific systemwide directory, specify the-XX:+CheckEndorsedAndExtDirs
command-line option. This causes the same exit behavior to occur if the directory exists and isn’t empty. The extension class loader is retained in JDK 9 and is specified as the platform class loader (seegetPlatformClassLoader.)
The following error means that your system is configured to use the extension mechanism:
<JAVA_HOME>/lib/ext exists, extensions mechanism no longer supported; Use -classpath instead..Error: Could not create the Java Virtual Machine.Error: A fatal exception has occurred. Program will exit.
You’ll see a similar error if thejava.ext.dirs
system property is set.
To fix this error, remove theext/
directory or thejava.ext.dirs
system property.
Thejava.endorsed.dirs
system property and thelib/endorsed
directory are no longer present. Thejavac
compiler andjava
launcher will exit if either one is detected.
In JDK 9, you can use upgradeable modules or put the JAR files on the class path.
This mechanism was intended for application servers to override components used in the JDK. Packages to be updated would be placed into JAR files, and the system propertyjava.endorsed.dirs
would tell the Java runtime environment where to find them. If a value for this property wasn’t specified, then the default of$JAVA_HOME/lib/endorsed
was used.
In JDK 8, you can use the-XX:+CheckEndorsedAndExtDirs
command-line argument to check for such directories anywhere on the system.
In JDK 9, thejavac
compiler andjava
launcher will exit if thejava.endorsed.dirs
system property is set, or if thelib/endorsed
directory exists.
The following error means that your system is configured to use the endorsed standards override mechanism:
<JAVA_HOME>/lib/endorsed is not supported. Endorsed standards and standalone APIsin modular form will be supported via the concept of upgradeable modules.Error: Could not create the Java Virtual Machine.Error: A fatal exception has occurred. Program will exit.
You’ll see a similar error if thejava.endorsed.dirs
system property is set.
To fix this error, remove thelib/endorsed
directory, or unset thejava.endorsed.dirs
system property.
The JRE installer creates keys in the Windows registry that have a different name than in previous releases. These changes may impact existing applications that use these keys.
If your application searches the registry for the installed version of Java it may fail, as theJava Runtime Environment
key, which is created in Java SE 8 and previous releases, is abbreviated toJRE
in Java SE 9.
“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JRE”
“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JRE\9”
"HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JRE""@CurrentVersion"=9
If the JDK is installed, theJDK
key replaces theJRE
key in the above example.
“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment”
“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.8”
“HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.8.0_144”
"HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment""@CurrentVersion"=1.8
If the JDK is installed, theJava Development Kit
key replaces theJava Runtime Environment
key in the above example.
If there are two versions of JDK or JRE installed, one with the new version-string format introduced in JDK 9, and the other with the older version format, then there will be two different Java-relatedCurrentVersion
strings in the registry. One indicates the highest version number prior to JDK 9, and the other indicates the highest version number since JDK 9.
This section highlights APIs that have been made inaccessible, removed, or altered in their default behavior. You may encounter the issues described in this section when compiling or running your application.
The Java team is committed to backward compatibility. If an application runs in JDK 8, then it will run on JDK 9 as long as it uses APIs that are supported and intended for external use.
These include:
Supported APIs can be removed from the JDK, but only with notice. Find out if your code is using deprecated APIs by running the static analysis tooljdeprscan
.
java.* APIs that have been removed in JDK 9 include the previously deprecated methods from thejava.util.logging.LogManager andjava.util.jar.Pack200 packages:
java.util.logging.LogManager.addPropertyChangeListenerjava.util.logging.LogManager.removePropertyChangeListenerjava.util.jar.Pack200.Packer.addPropertyChangeListenerjava.util.jar.Pack200.Packer.removePropertyChangeListenerjava.util.jar.Pack200.Unpacker.addPropertyChangeListenerjava.util.jar.Pack200.Unpacker.removePropertyChangeListener
Unlike thejava.* APIs, almost all of thesun.* APIs are unsupported, JDK-internal APIs, and may go away at any time.
A fewsun.* APIs have been removed in JDK 9. Notably,sun.misc.BASE64Encoder andsun.misc.BASE64Decoder have been removed. Instead, use the supportedjava.util.Base64 class, which was added in Java SE 8.
The functionality of many of the methods in this class is available by using variable handles, seeJEP 193: Variable Handles.
Instead, use the stack-walking API, seeJEP 259: Stack-Walking API.
Thejava.awt.peer andjava.awt.dnd.peer packages aren’t accessible in JDK 9. The packages were never part of the Java SE API, despite being in thejava.* namespace.
All methods in the Java SE API that refer to types defined in these packages have been removed from JDK 9. Code that calls a method that previously accepted or returned a type defined in these packages no longer compiles or runs.
if (component.getPeer() != null) { .. }Replace this withComponent.isDisplayable() from the JDK 1.1 API:
public boolean isDisplayable() { return getPeer() != null;
if (component.getPeer() instanceof LightweightPeer) ..Replace this withComponent.isLightweight() from the JDK 1.2 API:
public boolean isLightweight() { return getPeer() instanceof LightweightPeer;
The nonstandard packagecom.sun.image.codec.jpeg has been removed. Use the Java Image I/O API instead.
Thecom.sun.image.codec.jpeg package was added in JDK 1.2 as a nonstandard way of controlling the loading and saving of JPEG format image files. It has never been part of the platform specification.
In JDK 1.4, the Java Image I/O API was added as a standard API, residing in thejavax.imageio package. It provides a standard mechanism for controlling the loading and saving of sampled image formats and requires all compliant Java SE implementations to support JPEG based on the Java Image I/O specification.
In JDK 9, you can choose to build and run your application against any subset of the modules in the Java runtime image, without needing to rely on predefined profiles.
Profiles, introduced in Java SE 8, define subsets of the Java SE Platform API that can reduce the static size of the Java runtime on devices that have limited storage capacity. The tools in JDK 8 support three profiles,compact1
,compact2
, andcompact3
. For the API composition of each profile, seeDetailed Profile Composition andAPI Reference in the JDK 8 documentation.
In JDK 8, you use the-profile
option to specify the profile when running thejavac
andjava
commands. In JDK 9, the-profile
option is supported byjavac
only in conjunction with the--release 8
option, and isn’t supported byjava
.
JDK 9 lets you choose the modules that are used at compile and run time. By specifying modules with the new--limit-modules
option, you can obtain the same APIs that are in the compact profiles. This option is supported by both thejavac
andjava
commands, as shown in the following examples:
javac --limit-modules java.base,java.logging MyApp.java
java --limit-modules java.base,java.logging MyApp
For thecompact1
profile:java.base,java.logging,java.scripting
For thecompact2
profile:java.base,java.logging,java.scripting,java.rmi,java.sql,java.xml
For thecompact3
profile:java.base,java.logging,java.scripting,java.rmi,java.sql,java.xml,java.compiler,java.instrument,java.management,java.naming,java.prefs,java.security.jgss,java.security.sasl,java.sql.rowset,java.xml.crypto
You can use thejdeps
tool to do a static analysis of the Java packages that are being used in your source code. This gives you the set of modules that you need to execute your application. If you had been using thecompact3
profile, for example, then you may see that you don’t need to include that entire set of modules when you build your application. Seejdeps
inJava Platform, Standard Edition Tools Reference.
In JDK 9, the Unicode Consortium's Common Locale Data Repository (CLDR) data is enabled as the default locale data, so that you can use standard locale data without any further action.
In JDK 8, although CLDR locale data is bundled with the JRE, it isn’t enabled by default.
Code that uses locale-sensitive services such as date, time, and number formatting may produce different results with the CLDR locale data. Remember that evenSystem.out.printf() is locale-aware.
To enable behavior compatible with JDK 8, set the system propertyjava.locale.providers
to a value withCOMPAT
ahead ofCLDR
, for example,java.locale.providers=COMPAT,CLDR
.
SeeCLDR Locale Data Enabled by Default in theJava Platform, Standard Edition Internationalization Guide andJEP 252: Use CLDR Locale Data by Default.
In JDK 9, the modules that contain CORBA or the APIs shared between Java SE and Java EE are not resolved by default when you compile or run code on the class path. These are:
Existing code with references to classes in these APIs will not compile without changes to the build. Similarly, code on the class path with references to classes in these APIs will fail withNoDefClassFoundError
orClassNotFoundException
unless changes are made in how the application is deployed.
The code for these APIs was not removed in JDK 9, although the modules are deprecated for removal. The policy of not resolving these modules is a first step toward removing these APIs from Java SE and the JDK in a future release.
The migration options for libraries or applications that use these APIs are:
Use the--add-modules
command-line option to ensure that the module with the API is resolved at startup. For example, specify--add-module java.xml.bind
to ensure that thejava.xml.bind module is resolved. This allows existing code that uses the JAXB API and implementation to work as it did in JDK 8.
This is a temporary workaround because eventually these modules will be removed from the JDK.
Using--add-modules java.se.ee
or--add-modules ALL-SYSTEM
as a workaround is not recommended. These options will resolve all Java EE modules, which is problematic in environments that are also using the standalone versions of APIs.
Deploy the standalone version of the API (and implementation if needed) on the class path. Each of the Java EE APIs are standalone technologies with projects published in Maven Central.
Deploy the standalone version of these modules on the upgrade module path. The standalone versions are provided by the Java EE project.
The ability to request a version of the JRE that isn’t the JRE being launched at launch time is removed in JDK 9.
Modern applications are typically deployed using Java Web Start (JNLP), native OS packaging systems, or active installers. These technologies have their own methods to manage the JREs needed, by finding or downloading and updating the required JRE, as needed. This makes the launcher's launch-time JRE version selection obsolete.
In the previous releases, you could specify what JRE version (or range of versions) to use when starting an application. Version selection was possible through both a command-line option and manifest entry in the application's JAR file.
java
launcher is modified as follows:-version:
option is given on the command line.JRE-Version
manifest entry is found in a JAR file.In JDK 9, the ability to deploy an applet as a serialized object isn’t supported. With modern compression and JVM performance, there’s no benefit to deploying an applet in this way.
Theobject
attribute of theapplet
tag and theobject
andjava object
applet parameter tags are ignored when starting applet.
Instead of serializing applets, use standard deployment strategies.
JNLP (Java Network Launch Protocol) has been updated to remove inconsistencies, make code maintenance easier, and enhance security.
JNLP has been updated as follows:
&
instead of&
in JNLP files.The JNLP file syntax conforms to the XML specification and all JNLP files should be able to be parsed by standard XML parsers.
JNLP files let you specify complex comparisons. Previously, this was done by using the ampersand (&
), but this isn’t supported in standard XML. If you’re using&
to create complex comparisons, then replace it with&
in your JNLP file.&
is compatible with all versions of JNLP.
Comparing numeric version element types against nonnumeric version element types.
Previously, when anint
version element was compared with another version element that couldn’t be parsed as anint
, the version elements were compared lexicographically by ASCII value.
In JDK 9, if the element that can be parsed as anint
is a shorter string than the other element, it will be padded with leading zeros before being compared lexicographically by ASCII value. This ensures there can be no circularity.
In the case where both version comparisons and a JNLP servlet are used, you should use only numeric values to represent versions.
java
(orj2se
) elements.This is permitted in the specification. It was previously supported, but this support wasn’t reflected in the specification.
The JNLP specification has been enhanced to add atype
attribute toapplication-desc
element, and add the subelementparam
inapplication-desc
(as it already is inapplet-desc
).
This doesn’t cause problems with existing applications because the previous way of specifying a JavaFX application is still supported.
See the JNLP specification updates atJSR-056.
If your application previously required the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files, then you no longer need to download or install them. They are included in the JDK and are activated by default.
If your country or usage requires a more restrictive policy, the limited Java cryptographic policy files are still available.
If you have requirements that are not met by either of the policy files provided by default, then you can customize these policy files to meet your needs.
See thecrypto.policy
Security property in the<java-home>/conf/security/java.security
file, orCryptographic Strength Configuration in theJava Platform, Standard Edition Security Developer's Guide.
You are advised to consult your export/import control counsel or attorney to determine the exact requirements.
We recommend that you use the PKCS12 format for your keystores. This format, which is the default keystore type, is based on the RSA PKCS12 Personal Information Exchange Syntax Standard.
SeeCreating a Keystore to Use with JSSE inJava Platform, Standard Edition Security Developer's Guide andkeytool inJava Platform, Standard Edition Tools Reference.
The Garbage-First Garbage Collector (G1 GC) is the default garbage collector in JDK 9.
A low-pause collector such as G1 GC should provide a better overall experience, for most users, than a throughput-oriented collector such as the Parallel GC, which is the JDK 8 default.
SeeErgonomic Defaults for G1 GC andTunable Defaults inJava Platform, Standard Edition Java Virtual Machine Guide for more information about tuning G1 GC.
The following GC combinations will cause your application to fail to start in JDK 9:
DefNew + CMS
ParNew + SerialOld
Incremental CMS
The foreground mode for CMS has also been removed. The command-line flags that were removed are-Xincgc
,-XX:+CMSIncrementalMode
,-XX:+UseCMSCompactAtFullCollection
,-XX:+CMSFullGCsBeforeCompaction
, and-XX:+UseCMSCollectionPassing
.
The command-line flag-XX:+UseParNewGC
no longer has an effect. TheParNew
flag can be used only with CMS and CMS requiresParNew
. Thus, the-XX:+UseParNewGC
flag has been deprecated and is eligible for removal in a future release.
SeeJEP 214: Remove GC Combinations Deprecated in JDK 8.
Removed Permanent Generation
The permanent generation was removed in JDK 8, and the related VM options cause a warning to be printed. You should remove these options from your scripts:
-XX:MaxPermSize=size
-XX:PermSize=size
Java HotSpot(TM) 64-Bit Server VM warning: Ignoring option MaxPermSize; support was removed in 8.0
Tools that are aware of the permanent generation may have to be updated.
SeeJEP 122: Remove the Permanent Generation andJDK 9 Release Notes - Removed APIs, Features, and Options .
Garbage collection (GC) logging uses the JVM unified logging framework, and there are some differences between the new and the old logs. Any GC log parsers that you’re working with will probably need to change.
You may also need to update your JVM logging options. All GC-related logging should use thegc
tag (for example,—Xlog:gc
), usually in combination with other tags. The—XX:+PrintGCDetails
and-XX:+PrintGC
options have been deprecated.
SeeEnable Logging with the JVM Unified Logging Framework in theJava Platform, Standard Edition Tools Reference andJEP 271: Unified GC Logging.
This list includes tools and components that are no longer bundled with JDK 9.
JavaDB, which was a rebranding of Apache Derby, isn’t included in JDK 9.
JavaDB was bundled with JDK 7 and JDK 8. It was found in thedb
directory of the JDK installation directory.
You can download and install Apache Derby fromApache Derby Downloads.
Thehprof
agent library has been removed.
Thehprof
agent was written as demonstration code for theJVM Tool Interface and wasn’t intended to be a production tool. The useful features of thehprof
agent have been superseded by better alternatives, including some that are included in the JDK.
For creating heap dumps in thehprof
format, use a diagnostic command (jcmd
) or thejmap
tool:
For CPU profiler capabilities, use the Java Flight Recorder, which is bundled with the JDK.
Note:
Java Flight Recorder requires a commercial license for use in production. To learn more about commercial features and how to enable them, visithttp://www.oracle.com/technetwork/java/javaseproducts/.Thejhat
tool was an experimental, unsupported heap visualization tool added in JDK 6. Superior heap visualizers and analyzers have been available for many years.
The launchersjava-rmi.exe
from Windows andjava-rmi.cgi
from Linux and Solaris have been removed.
java-rmi.cgi
was in$JAVA_HOME/bin
on Linux and Solaris.
java-rmi.exe
was in$JAVA_HOME/bin
on Windows.
These launchers were added to the JDK to facilitate use of the RMI CGI proxy mechanism, which was deprecated in JDK 8.
The alternative of using a servlet to proxy RMI over HTTP has been available, and even preferred, for several years. SeeJava RMI and Object Serialization.
The IIOP transport support from the JMX RMI Connector along with its supporting classes have been removed in JDK 9.
In JDK 8, support for the IIOP transport was downgraded from required to optional. This was the first step in a multirelease effort to remove support for the IIOP transport from the JMX Remote API. In JDK 9, support for IIOP has been removed completely.
Public API changes include:
Thejavax.management.remote.rmi.RMIIIOPServerImpl
class has been deprecated. Upon invocation, all its methods and constructors throwjava.lang.UnsupportedOperationException
with an explanatory message.
Two classes,org.omg.stub.javax.management.rmi._RMIConnection_Stub
, andorg.omg.stub.javax.management.rmi._RMIConnection_Tie
, aren’t generated.
In JDK 9, the Windows 32–bit client VM is not available. Only a server VM is offered.
JDK 8 and earlier releases offered both a client JVM and a server JVM for Windows 32-bit systems. JDK 9 offers only the server JVM. The server JVM is tuned to maximize peak operating speed.
Java VisualVM is a tool that provides information about code running on a Java Virtual Machine. Thejvisualvm
tool was provided with JDK 6, JDK 7, and JDK 8.
Java VisualVM isn’t bundled with JDK 9. If you would like to use VisualVM with JDK 9, then you can get it from theVisualVM open source project site.
Thenative2ascii
tool is removed in JDK 9. Because JDK 9 supports UTF-8 based properties resource bundles, the conversion tool for UTF-8 based properties resource bundles to ISO-8859-1 is no longer needed.
SeeUTF-8 Properties Files inJava Platform, Standard Edition Internationalization Guide.
This section includes macOS-specific features that have been removed in JDK 9.
Thejava.awt.Desktop
class contains replacements for the APIs in the Apple–specificcom.apple.eawt
andcom.apple.eio
packages. The new APIs supersede the macOS APIs and are platform-independent.
The APIs in thecom.apple.eawt
andcom.apple.eio
packages are encapsulated, so you won’t be able to compile against them in JDK 9. However, they remain accessible at runtime, so existing code that is compiled to old versions continues to run. Eventually, libraries or applications that use the internal classes in the apple
andcom.apple
packages and their subpackages will need to migrate to the new API.
Thecom.apple.concurrent
andapple.applescript
packages are removed without any replacement.
The AppleScript engine, a platform-specificjavax.script implementation, has been removed without any replacement in JDK 9.
The AppleScript engine has been mostly unusable in recent releases. The functionality worked only in JDK 7 or JDK 8 on systems that already had Apple's version of theAppleScriptEngine.jar
file on the system.
After you have your application working on JDK 9, here are some suggestions that can help you get the most from the Java SE Platform:
ReadJava Platform, Standard Edition What's New in JDK 9 to learn about new features of JDK 9.
If needed, cross-compile to an older release of the platform using the new–release
flag in thejavac
tool.
Take advantage of your IDE’s suggestions for updating your code with the latest features.
Find out if your code is using deprecated APIs by running the static analysis tooljdeprscan
. As already mentioned in this guide, APIs can be removed from the JDK, but only with advance notice.
Get familiar with new features like multi-release JAR files (seejar
) .
For information about Oracle's commitment to accessibility, visit the Oracle Accessibility Program website athttp://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc.
Access to Oracle Support
Oracle customers that have purchased support have access to electronic support through My Oracle Support. For information, visithttp://www.oracle.com/pls/topic/lookup?ctx=acc&id=info or visithttp://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs if you are hearing impaired.
Java Platform, Standard Edition Oracle JDK 9 Migration Guide,Release 9
E82965-05
Copyright © 2017, Oracle and/or its affiliates. All rights reserved.
This guide will help you migrate your application to Oracle JDK 9.
This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.
The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.
If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, then the following notice is applicable:
U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs. No other rights are granted to the U.S. Government.
This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.
Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.
Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.
This software or hardware and documentation may provide access to or information about content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services unless otherwise set forth in an applicable agreement between you and Oracle. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services, except as set forth in an applicable agreement between you and Oracle.