JDK 9: Pitfalls For The Unwary
Jul 11, 2017 | 13 MIN READ
Jul 11, 2017 | 13 MIN READ
JDK 9 is in the final phases of development, heading towards release on September 21st. The public review consideration ballot for the Java Platform Module System was passed [almost] unanimously, and so everything is now back on track.
You can download the Azul Zulu builds of OpenJDK 9 here.
Recently I’ve been doing a presentation entitled, “55 New Features in JDK 9”. In this, I’ve tried to focus almost entirely on things that are not JPMS. What this has revealed is that there are a few areas of change in JDK 9 that could catch people out regarding compatibility with earlier versions. I’ve also been noticing a number of questions related to these things appearing on Stackoverflow
This blog is a summary of all the things I’ve been able to find that might require you to change something when migrating your applications to JDK 9. What I’m not going to do here is talk about JPMS, encapsulation of non-public classes, effects on reflective access and so on. That’s a whole different set of issues. This collection is just about the other things that you need to be aware of.
_ -> foo())
$JAVA_HOME, you may need to make some changes. There’s a number of distinct differences here:
tools.jarfiles. If you access these directly, you will need to change your code.
bin/hprof.dllon Windows) files have been deleted as well.
JDK 8u131, for example, but if you run
java -versionyou’ll get back
java version "1.8.0_131". To simplify this for both humans and applications, the format is now
JDK $MAJOR.$MINOR.$SECURITY.$PATCH, so
java -versionon JDK9 returns
java version "9"(this will change once the release is final and we start getting updates). The important thing here is that, if you use the version string of the JVM in your code and rely on the current format you’ll have to make changes to run correctly on JDK 9.
Thread.stop(Throwable)now throws an
UnsupportedOperationException, which it did not do before. This method has been deprecated since deprecation first started due to its inherent lack of thread safety. The other version of
Thread.stop(), which takes no arguments will still work without throwing an exception (but is still deprecated and you are strongly advised not to use this).
$JAVA_HOME/lib/endorseddirectories have been deleted. If you recreate these and try putting things in them in the hope that this will still work, it won’t. The JVM will fail to start of it finds these directories, and you will get the following error message:
<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.
com.sun.security.auth.callback.DialogCallbackHandlerclass, which was part of the Java Authentication and Authorization Service (JAAS), has been removed. This was deprecated in JDK 8.
-version:<version-id>option. If you use this, the JVM will abort without starting. The second way was from the manifest of a jar file. In this case, JDK 9 will ignore the directive but start up normally. It was felt that forcing people to change the manifest was too onerous compared to changing the command line. Please note that the
-versionoption (without a following colon and version-id) still works quite happily to report which version of the Java runtime you have.
-XX:-UseParNewGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -Xincgc -XX:+CMSIncrementalMode -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+UseConcMarkSweepGC -XX:-UseParNewGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSFullGCsBeforeCompaction -XX:+UseCMSCollectionPassing
In JDK 9, the incremental mode of concurrent-mark-sweep (iCMS) has been removed, and the current plan is to remove CMS completely in JDK 10
This seems to be quite a big change to me, yet I’ve not seen it highlighted (or well documented) so far.
Aside from the GC options noted above, there is a significant change in how logging is handled by the JVM. JEP 158 introduces the Unified Logging system, and this is used by GC logging to provide Unified GC logging (JEP 271). This affects a number of commonly used GC logging command line options as well as some other things.
To figure out exactly what had changed I extracted the relevant lines from the OpenJDK source code (specifically, the
src/share/vm/runtime/globals.hpp file). By doing a diff, I was able to get a list of all the
-XX options that had been removed from JDK 8 and all those that had been added to JDK 9. I then wrote a script to use each in turn with a simple app to see what the result of using the options that had been removed from JDK 8 was on JDK 9.
The changes to
-XX options can be separated into three groups:
If you use one of these, you will get the following warning message, but the JVM will start normally.
Java HotSpot(TM) 64-Bit Server VM warning: Ignoring option <Option>; support was removed in 9.0
<h3id=”DeprecatedOptions”>Deprecated Command-Line Options
These options will issue a warning when the JVM starts, either telling you which option will be used instead by the JVM or telling you which option you should use. Most of these are related to the move to unified GC logging.
Here are two examples of the warning messages:
warning][gc] -XX:+PrintGC is deprecated. Will use -Xlog:gc instead. Java HotSpot(TM) 64-Bit Server VM warning: Option CreateMinidumpOnCrash was deprecated in version 9.0 and will likely be removed in a future release. Use option CreateCoredumpOnCrash instead.
The table below shows the JDK 8 command line option and the JDK 9 replacement.
|JDK 8 Option||JDK 9 Replacement|
These are the most significant options regarding compatibility. If you have used these in the past and don’t change your command line, your application won’t start. When you use one of these you will get the following error message:
Unrecognized VM option '<Option>' Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit.
Here’s the list of 50 options that won’t work with JDK 9. Check to see if you’ve used any of these in your command line and startup scripts.
Hopefully, this will help you check whether there are any changes you need to make to your application and its configuration as you migrate to JDK 9.