Java Standard Edition (JSE) 9 (‘Java 9’) was finally completed and publicly released at the end of Sept 2017. This post contains a brief overview of what’s new in Java 9, and outlines the main reasons why you or your business might consider upgrading, if at all. It also provides developers with a link to a set of code examples that I’ve produced, which showcase the major new language features in Java 9 and explains each of them in more detail.
1) The Java Platform Module System (JPMS)
The Java Platform Module System (JPMS), aka Project Jigsaw, is by far the biggest new feature in Java 9. It affects all areas of Java including the platform libraries, the language and runtime. Whilst its design was controversial, and the reason for the lengthy repeat delays that occurred in completing Java 9, JPMS required a massive engineering effort on the part of Oracle’s Java engineers and other contributors. They should be congratulated and thanked for the benefits it will deliver in the future. Broadly speaking, JPMS delivers the following major benefits –
1) Modularisation of the Java platform – The Java SE APIs and codebase had grown large and unwieldy (totaling ~4.5k classes) over time, with a lot of tangled dependencies between seemingly unrelated packages, and sometimes dependencies on legacy code in the platform. Project Jigsaw has addressed this technical debt by splitting the platform up into (over 90 different) modules. In the process, dependencies between platform code have been untangled and sanitised (including removing cyclic dependencies).
2) Smaller Runtimes – On top of the modularisation, JPMS has also added support for producing custom runtime versions of Java, which only contain those part of the platform that are essential for its core operation and needed by your app(s). These custom Java distributions have a smaller (memory and disk-space) footprint allowing Java to be run on smaller devices with less hardware resources. This bodes well for Java future as it makes it better placed to support some of the increasingly popular and emerging runtime environments and domains such as mobile platforms (e.g. new releases of Android); the proliferation of smaller devices (e.g. Raspberry PI and similar) supporting the growing Internet of Things (IoT); and applications running in Linux containers (e.g. Docker).
3) Language-level support for modularising applications built on Java – In addition to modularising the Java platform’s APIs and code, JPMS adds first-class support for defining modules at the Java language level (alongside existing language concepts such as packages and classes). This offers several new potential benefits when designing and building your own Java applications.
- Stronger encapsulation – Logically speaking a module comprises of a set of public APIs and an internal implementation. The platform now provides a mechanism for restricting (preventing public) access to the module’s internal implementation, by stating (exporting) which packages can and can’t be externally accessed. This has the benefit of reducing the surface area and no. of dependencies on the module, allowing the implementation of the module to change and evolve without risk of introducing breaking changes in the future.
- Reduction in runtime conflicts – The JPMS introduces the new concept of a module path, which defines the classes that are available to an app at runtime. This is the way the JVM enforces the aforementioned access restrictions to packages within modules. Module encapsulation and its enforcement at runtime provide increased control on what Java classes are visible or accessible to class-loaders at runtime, and goes some way to helping reduce the runtime conflicts seen with the Java classpath.
Java 9 does not mandate the use of the new module system. As you would expect there is full backwards compatibility allowing existing Java apps to run on Java 9.
Personally I would not recommend trying to modularise an existing application using the JPMS. However, its use should certainly be considered if you’re building a new library or app on Java 9. However, the perceived wisdom in the Java community is that you’re best to defer the use of the JPMS to modularise an app at least until all the major 3rd party framework and library providers have got their own house in order, including settling on their module naming strategies.
2) Performance Improvements
As has been the case for most major new Java releases there have been some performance improvements made to the platform and JVM. And I’d suggest (given the lack of major new language features) this is the main reason for considering upgrading to Java 9.
One area in which performance has been improved is the JVM’s storage of Strings in memory. Prior to Java 9 all Strings were stored as character arrays (char) and encoded using UTF-16, resulting in them requiring 2 bytes of memory. This can be a waste of (heap) memory given that many strings only contain characters that can be encoded in a byte, using char encodings such as ASCII, and UTF-8. A Java 9 feature referred to as ‘Compact strings’, has enhanced both the JVM and implementation of the String class such that the JVM now only uses a single-byte to store a string whenever possible. This feature is enabled by default for a Java 9 JVM, and has the potentially to significantly reduce the amount of (heap) memory required by Java apps.
Java 9 adds a Read-Evaluate-Print-Loop (REPL) that allows you to more easily explore the Java APIs and run arbitrary Java code than having to write a Java application with a main method, and go through the compile and run steps.
The main benefit of the REPL would seem to be to make it easier for people to learn Java. It certainly makes it a lot easier to teach Java and for individuals to get started writing Java than the previous need to explain and write a class, a main method; compile your code using the java compiler (javac) from the command line, ensuring your specify the correct classpath; and finally run your code (java).
For the experienced Java developer though, the value of the REPL is open to question, given that an IDE offers better code completion and already removes the manual compile and run steps. That said, I think the REPL may still come in handy for confirming the behaviour of Java APIs and libraries, and maybe sketching / prototyping trivial apps.
4) Overview of New Language Features
Beyond JPMS, whilst It’s fair to say that there aren’t any major new language features for Java developers to get excited about, as there were in Java 8 (such as the Stream API and Lambdas), there are still a few features that make it worth considering upgrading. These less well publicised new language features in Java 9 include:
- Factory methods for Collections
- Private methods in interfaces
- java.util.Optional enhancements
- Stream API enhancements
- Reactive Streams API standard implementation
- Process API enhancements
- CompletableFuture enhancements
- Effectively final variables in try-with-resources blocks
I’ve produced a set of easy to run Java code examples for a number of these new language features, which illustrate and explain them in more detail. You can find the code on GitHub at https://github.com/neiljbrown/java9-examples.
5) Other New Features
In addition to the major features, and set of minor language features, mentioned above, there are also some other changes in Java 9 that might be of value to you, e.g.
- Upgraded Unicode support – Java 9 now supports the more recent versions (7 and 8) of Unicode standard. This adds support for ~10k additional characters for some new (e.g. African) languages, although that aside they’re mostly more emojis…..
- UTF-8 Property files – Long overdue support for storing and reading UTF-8 encoded characters from properties files. This removes a need for a custom solution adopted in most of my projects that have I18N requirements.
6) So, should you upgrade?
Having established above what Java 9 has to offer, should you / your business upgrade your existing apps to Java 9, and / or adopt it for your new apps?
For most business, the main motivations for upgrading existing Java apps will be the potential performance benefits. Performance test your apps and see whether things like compact Strings offer a significant benefit (reduced memory requirements). The ability to create smaller, custom Java runtimes (using the jlink tool) is another reason to upgrade to Java 9. In Java 8, Docker images that include a JRE are ~500MB in size. Reducing this size could make the upload of new releases and the copying/download of those images by runtime platforms and container scheduling and orchestration tools significantly faster. A smaller no. of business may benefit from other features like better Unicode support.
If writing new apps or libraries, then JPMS may offer compelling benefits for encapsulation and/or smaller runtimes. However, as noted above, it may be best to wait for all your third-party library providers to adopt Java modules first and then let the dust settle.
Unfortunately, whilst I would have unreservedly said yes to adopting Java 9, there is one reason which may cause many businesses to skip it. Oracle has announced that they will not be providing long term support for Java 9. This decision is closely linked to Oracle’s proposed more frequent (half-yearly) release plan for Java. What this means in practice, is that Java 9 will only receive maintenance releases for security and bugs until the next release of Java (10), which is due March 2018. The previous Java 8 release, for which long term support is provided, will continue to receive public maintenance releases for more than 9 months longer, until at least January 2019. The next release of Java for which long term maintenance will be provided will be Java 11, which is currently scheduled for Sept 2018. (For more details and the latest dates see Oracle Java SE Support Roadmap). There is therefore a strong argument for business’ using Java (for server apps at least) to stay on Java 8 and skip upgrading or adopting new releases of Java (at least in production) until Java 11. Of course, that will depend on what valuable new features are in the intervening Java 10. release.
I think it’s a reasonable decision to wait for Java 11, if there are no other compelling reasons to upgrade, such as performance. However, in the meantime it’s a good idea to trial upgrading to Java 9, even if you chose not to adopt it in production, to see how much effort is likely to be involved.
Remember to check-out my Java 9 code examples, and let me know if you find them useful (e.g. by staring the project on GitHub).