Last year I took a quick look at the newly released Java SE 9 but wanted to delay updating until the corresponding NetBeans version was out. Nothing happened, so that’s the first incompatibility to discuss, followed by JavaMail and JavaFX issues.
After four months NetBeans is still in Apache incubator limbo with no sign of an official Java 9 release appearing anytime soon. So rather than waiting for who knows when, I decided to switch to IntelliJ IDEA which has already had three point releases during the same time period. IntelliJ originated as a commercial product but today also offers a free open-source community edition that’s perfectly sufficient for Java development (and of course Kotlin).
There are some drawbacks compared to NetBeans: the IDE is slower, with noticeable delays even on a beefy machine; and its greater flexibility results in a steeper initial learning curve. On the upside, IntelliJ is a good deal more powerful and professionally polished than NetBeans. It’s a relief to finally have a code analyzer that produces sensible reports out of the box, for example. I don’t think I’ll regret this involuntary IDE switch.
JavaMail vs Modules
I had dismissed the issues covered in this detailed Java 9 Migration Guide as “fairly arcane.” Turns out I was wrong. The section “Dependencies On Java EE Modules” lists various APIs that were once upon a time copied from Java EE to SE for developer convenience, and are now in the process of being removed again (JEP 320). As a first step toward this, Java SE 9 hides them by default.
The non-arcane dependency I discovered concerns JavaMail, a popular email and messaging framework. JavaMail depends on
java.activation which happens to be one of those newly invisible Java EE modules. The JavaMail FAQ already adresses this issue: every startup of a Java SE 9 application that uses JavaMail must contain the command line flag
This workaround is rather unpleasant. The command line gets lengthy, it’s easy to forget this switch, and users can no longer simply double-click on an executable JAR file that needs JavaMail. Moreover, the
--add-modules trick won’t work once the hidden modules have been removed from a future Java SE release.
JEP 320 recommends a better solution: deploy standalone libraries for any required hidden Java EE feature. For
java.activation, a complete reference implementation (version 1.2) is available on the recently established Java EE project on GitHub. You can get the same version from Maven. (Strangely, JEP 320 links to a specification-only Maven artifact, and the JavaMail documentation to an ancient Sun download intended for Java 1.5!)
JavaFX vs Java SE 8
Java SE 9 is fairly new and can cause update headaches thanks to the new module system, so for the near future it’s safe to assume that most Java installations will use SE 8 at best. Let’s have a look at the various version configurations with regard to Java applications.
- Creating and running an application using the same Java version is unproblematic, of course.
- Creating an application with JDK 8 and running under Java 9 generally works, except for module-related failure cases like the one discussed above.
- Creating an application with JDK 9 and running under Java 8 should work, using the appropriate javac switches (
--release). There is one glaring exception: JavaFX.
If you try to build a JavaFX application under JDK 9 while targeting Java 8, any attempt to resolve any JavaFX type will fail and compilation will abort. Amazingly, this is by design! Oracle’s David Holmes explains the situation on the OpenJDK mailing list:
JavaFX is an extension provided as part of the JRE. The docs for
Compiles against the public, supported and documented API for a specific VM version.
I’d say that an extension does not fit that description (though I dislike the description as it refers to the VM). So yes you will need the fx jar file available.
If you want to target JavaFX 8 from JDK 9 you need to link against the actual
jfxrt.jar from JDK 8. I’m sure quite a few JavaFX developers will be surprised to hear that they were actually using an unsupported extension to Java SE 8. Oracle’s Jan Lahoda provides some further information:
--release <= 8, the historical data used by
--releasecontain class[es] for the default
javacbootclasspath for OpenJDK, which does not include JavaFX.
--release >= 9, this will probably need to be different (currently,
--release 9is supposed to include JavaFX if JavaFX is in the runtime image).
The “resolved/fixed” issue JDK-8188823 seems to indicate that JavaFX will indeed enjoy proper backward compatibility from Java 10 onward. In the meantime you might as well stick with JDK 8 for JavaFX development that needs to target Java 8.
Java AWT vs Font Leading
While porting my Class Diagrammer to Java SE 9, I found yet another incompatibility. It seems Java AWT used to have a bug where the recommended leading (interline spacing) of some fonts was ignored, i.e. TextLayout.getLeading always returned zero. As it happens this was the case for Adobe Myriad Pro which I use in my own class diagrams. The new text layout does look better but can increase the height of text blocks so much that I had to rearrange elements in a number of diagrams. This change may affect any precise text layout with AWT/Swing. (added 2018-02-15)