JDK 11: Pitfalls for the Unwary

I’m sure everyone now knows that the pace of change of the JDK has changed dramatically over the last year; we now have two major releases every year. One of the other substantial changes made to Java at the time JDK 9 was released was a different approach to compatibility. In the past, backward compatibility has been of paramount importance when delivering a new JDK. There’s nothing worse than taking tested, working code and having to modify and re-test the code just to get it working on a new version of the platform.

In the case of the JDK, this change was necessary because it was time to do some long overdue housekeeping and remove features that are of little or no use anymore. In addition, deprecation has been in the JDK right since JDK 1.1, but until JDK 9, no API elements had ever been removed, which rather defeated the whole purpose of having it.

The good news is that most applications will not be affected by these incompatibilities because, by definition, few applications are likely to be using these outdated features.

In previous blog posts, I’ve written about the changes in JDK 9 and JDK 10 that may affect migrating applications to these versions of Java. With JDK 11, a long-term support release, now having been out for a few weeks I figured it was time to catch up and list out things you should consider when migrating your applications.

Let’s break this down into the various areas of the JDK.

We can skip the Java language syntax, as there are no changes to this that will provide any issues (in fact, the only change at all is the very minor inclusion of the ability to use var with Lambda expression parameters).

Core Libraries

The biggest change in JDK 11 for libraries is the complete removal of the java.se.ee aggregator module. This includes the following modules:

  • java.corba: Common Object Request Broker Architecture. A very complicated (at least, in my opinion) way of developing distributed systems on heterogeneous platforms. Originally developed in the early 1990s, almost nobody I’ve spoken to uses this anymore, so it is unlikely to be missed.
  • java.transaction: A subset of the Java Transaction API that is only provided to support CORBA. This only includes three exception types.
  • java.activation: The Java Beans Activation Framework (JAF). This is a way for developers to determine the type of an arbitrary piece of data, encapsulate access to it, discover the operations available on the piece of data and instantiate the appropriate bean to perform the operations. Again, this appears to be a very little used feature.
  • java.xml.bind: Implementation of the Java API for XML Binding (JAXB). This is an API that may cause more problems for migration than the previous ones, as I’ve met a number of developers who still use JAXB.
  • java.xml.ws: Java API for XML-based Web Services (JAX-WS). Although pretty much everyone now uses RESTful web services, there are still a lot of people who have code developed using SOAP-based web services that require JAX-WS support to work. This is also set of APIs whose removal may catch a number of applications.
  • java.xml.ws.annotation: A subset of the common annotations API required for JAX-WS. Again, this is a very small module with only one enumeration and five annotations.

The good news is that, with the exception of CORBA support, all these modules have freely available versions, either as a reference implementation of the relevant standard or through Maven Central.

Here’s a list of other API elements that have been removed in JDK 11.

  • javax.security.auth.Policy: This class has been deprecated since JDK 1.4 and there is a direct replacement in the form of java.security.Policy. I think the likelihood of this affecting any applications is pretty small.
  • java.lang.Runtime.runFinalizersOnExit
     Both these methods were deprecated for removal all the way back in JDK 1.2 and are classified as inherently unsafe. There is no direct replacement.
  • java.lang.SecurityManager.checkAwtEventQueueAccess: Only recently deprecated in JDK 8, this method should be replaced by java.security.Permission.checkPermission with the AWTPermission(“accessEventQueue”) permission as a parameter. Since both methods throw a SecurityException if the permission is not accessible, this will require only a minor change.
  • java.lang.SecurityManager.checkMemberAccess: Replace with java.security.Permission.checkPermission (as above) with RuntimePermission(“accessDeclaredMembers”).
  • java.lang.SecurityManager.checkSystemClipboardAccess: Replace with java.security.Permission.checkPermission with AWTPermission(“accessClipboard”).
  • java.lang.SecurityManager.checkTopLevelWindow: Replace with java.security.Permission.checkPermission with AWTPermission(“showWindowWithoutWarningBanner”).
  • java.lang.Thread.destroy: Deprecated back in JDK 5.0, this method was, intriguingly, never implemented. If you’d used it all you would have got was a NoSuchMethodException.
  • java.lang.Thread.stop(java.lang.Throwable): This was deprecated all the way back in JDK 1.2. Note that there are two, overloaded versions of this method. This is the one that takes a Throwable as a parameter. The no-argument version is still available (although it is also deprecated and considered inherently unsafe).

JDK Changes

JDK 11 contains some significant changes because of the convergence of the Oracle JDK binary functionality with that of the OpenJDK. To achieve this, Oracle has removed the following major features from the Oracle JDK (which is most likely the one most people have been using up until now).

  • The Browser Plugin: This is essentially the end of Applets in Java. Although the Applet API remains in the java.desktop module, all of it is deprecated and I would expect to see this removed very soon. In addition to the plugin, the appletviewer tool has also been removed.
     If you are still using applets (there are a few die-hards out there), there is no migration path past JDK 8. If you want to continue getting security patches and bug fixes, you have no choice but to pay for an Oracle Java SE subscription. The browser plugin has not been released as open-source.
  • Java Web Start: This was a somewhat popular choice for delivering desktop Java applications over a decade ago but, with the majority of front-end applications using a browser and HTML5/CSS/Javascript it is only used by legacy applications.
     As part of the removal of this feature, the javaws command has been removed. The jcontrol (Java Control Panel) has also been removed that was used to configure both Web Start and the browser plugin.
     As with the browser plugin, Java Web Start has not been released as open-source and there is no simple alternative to this. There are a couple of projects that had the goal of replicating this functionality, but none of them have been touched in years. Other alternatives like getdown and install4j could be used but will require work and may not provide all the features required.
     Again, there is no migration path for this beyond JDK 8 with the same implications as for the browser plugin regarding updates.
  • JavaFX: This was never a part of the Java SE standard and, despite being an open-source project (OpenJFX) under the OpenJDK umbrella, is not part of the OpenJDK source for the JDK. Personally, I’m a big fan of JavaFX and have written a number of applications using this. There is also a small, but dedicated, group of users who build very impressive complex front-end applications for things like financial trading and scientific applications.
    The good news is that being a separate project, it is relatively straightforward to build binaries that can be added to a current JDK. Azul has recently released builds of the Zulu JDK that include JavaFX.
    In addition to the removal of the JavaFX modules, the javapackager (previously referred to as javafxpackager) command has been removed. JEP 343 has been proposed to provide a replacement packaging tool that is not tied to JavaFX.
  • Removal of the java.se.ee aggregator module: In addition to removing the modules discussed earlier, a number of related tools have also been removed from the JDK:
  • idlj (CORBA related)
  • orbd (CORBA related)
  • servertool (CORBA related)
  • tnamesrv (CORBA related)
  • schemagen (JAX-WS related)
  • wsgen (JAX-WS related)
  • wsimport (JAX-WS related)
  • xjc (JAX-WS related)
  • Java Mission Control: The jmc command was included as a commercial feature in the Oracle JDK prior to JDK 11. This has now been contributed by Oracle to the OpenJDK project and is available as a standalone package.

JVM Changes

There have been a lot of changes recently to the -XX command line flags available to configure the JVM. Below is a list of the flags that have been removed.

  • AttachListenerTimeout
  • CheckAssertionStatusDirectives
  • CheckEndorsedAndExtDirs
  • DeferPollingPageLoopCount
  • DeferThrSuspendLoopCount
  • EnableTracing
  • FastTLABRefill
  • G1RSBarrierRegionFilter
  • G1ScrubRemSets
  • G1SecondaryFreeListAppendLength
  • G1StressConcRegionFreeing
  • G1StressConcRegionFreeingDelayMillis
  • InlineNotify
  • MustCallLoadClassInternal
  • NativeMonitorFlags
  • NativeMonitorSpinLimit
  • NativeMonitorTimeout
  • PrintMalloc
  • PrintMallocFree
  • SafepointSpinBeforeYield
  • ShowSafepointMsgs
  • TraceScavenge
  • UnsyncloadClass
  • UseAppCDS
  • UseCGroupMemoryLimitForHeap
  • UseLockedTracing
  • UseUTCFileTimestamp

If you’re using any of these flags, you’ll need to look at alternative ways of doing the same thing. The two flags that I notice are:

  • UseAppCDS, which was a commercial feature and is now part of OpenJDK.
  • UseCGroupMemoryLimitForHeap The JVM is now properly CGroup aware so this is no longer required.


The reality is that most applications will move from JDK 10 to JDK 11 without issue. The only tricky bits will be if you’ve used anything fromjava.se.ee or older deployment technologies like applets or Java Web Start.

Remember, though, if you’re planning to migrate from JDK 8 to JDK 11 there are a few other changes that you’ll need to consider.