Java is arguably the most popular programming language, but what do developers need to know about the latest release, Java 9? Technologist and author Ben Evans is here to tell you.
Java 9 is finally here.
After several rounds of delays and a somewhat painful birth, the new version of the platform was released on 21 September 2017.
While many Java developers may be aware that Java 9 brings a new approach to code modularity (known as Java Platform Modules, or ‘Project Jigsaw’), the release seems not to have captured the same enthusiasm as we saw for Java 8.
So, what do Java developers need to know about Java 9?
The truth is, for most developers, Java 9 really does consist of ‘modules and then everything else’.
Just as Java 8 was all about lambdas and their consequences (streams, default methods and small aspects of functional programming), Java 9 is mostly about modules.
However, modules are a completely different type of feature than lambdas.
Lambdas can be introduced gradually to a Java project and give an immediate benefit to developers who begin using them, even if they start small.
Modules, on the other hand, are a new way of building and deploying software, and are not easy to adopt piecemeal.
Used from the ground up on a greenfield project, modules will help developers produce better architected software, which has a much smaller runtime footprint and will reduce complexity.
However, when trying to migrate an existing project to Java 9 and modules, there are some definite hurdles to overcome. The most striking of these is the change in behaviour of the ‘public’ keyword.
In Java 8 and below, anyone can call a public method on another class. With modules, this basic fact changes.
A module is made up of a group of related packages, and it can declare which of those packages form its API. Only methods that belong to classes in packages that are in the module’s API can be called.
This includes public methods – if a class is not part of the module API, then its public methods cannot be called. Reflection and method handles are no help either – even these types of calls are prevented by the new runtime.
In Java 9, an attempt to access a non-API method is known as an ‘illegal access’.
The intention is that over time, all illegal accesses will be removed from the platform and applications.
This will produce better software and also allow the Java platform team freedom to upgrade and modify the internals of the platform without the danger that they will break existing applications.
Unfortunately, as it stands, virtually all applications have some sort of illegal access in them.
Even if an application does not call any non-API methods directly, then it is almost certain that they are making use of a library that does.
In particular, there is a platform class called sun.misc.Unsafe, which provides access to non-standard features and methods that let a library break some of the rules of the Java platform.
Without access to general reflection and to this class, very few Java frameworks or libraries will run correctly.
This means that, in practice, very few real applications will run correctly without illegal access.
To help ease the transition and encourage library developers to do the right thing, Oracle has introduced a flag called ‘–illegal-access=<value>’ to temporarily allow (or warn) when access to internal packages is attempted.
The default in Java 9 is to allow access but this will be changed in a future release to deny access by default.
Full retest required
There are some other important consequences of the arrival of modules.
Some major libraries (including Spring and Maven) require a version upgrade to work out of the box with Java 9.
This leads to the ‘library lockstep’ problem where, alongside the Java version, an application’s dependencies may also need to be updated as part of the upgrade.
This means that the upgrade from 8 to 9 is not a drop-in replacement (as many upgrades from 7 to 8 were) and a full retest will be required for applications moving to 9, with the expectation that some remediation work will be necessary.
Developers also need to know about ‘multi-release jars’.
These are needed because not all changes that occur in 9 are fully backwards-compatible, so a mechanism was needed to ship a jar, which contains classes that use 9-specific features, but which will also work on Java 8.
If the jar has the multi-release flag set in MANIFEST.MF, then the runtime includes some additional version-specific paths in its classpath resolution.
As Java 8 doesn’t know about this flag, it ignores it, and the versioned directories are not included.
This feature is intended to ease the pain of library developers, who need to support both their existing Java 8 users as well as Java 9 apps.
The final word on Java 9 modules should be that they represent a very modern way to build well-architected apps. However, it may take teams and projects a while to see the long-term benefits of adopting modules.
Aside from modules, there are some other changes that are relevant to the developer in Java 9.
There are some small improvements to the libraries as well, including convenience factory methods for Collections. This means that we can write a single line of code to create an initialise a Set, List or Map, like this: Set<String> set = Set.of(“a”, “b”, “c”).
As an added benefit, the collection that we get back from one of these factories is also immutable.
It’s a small improvement but one that will hopefully make developers’ lives a little easier in the coming years.
Other library updates include some useful new functionality in the Java Streams API, including new methods and classes to better support the reactive paradigm.
A new API
There’s a new API for managing operating system processes for developers who need to write batch jobs and control systems.
Oracle has also taken the opportunity to bring Java’s HTTP capabilities up to date with support for the new HTTP/2 protocol.
This API is still under development, so it has been shipped as an ‘incubator’ module, meaning that developers can get access to it now and start using it, eg in microservices developments.
The API may change a little in the coming releases before being standardised, so the incubator mechanism is a useful way to alert developers to this possibility.
For learning new APIs, both those in the JDK and new external libraries, JShell is a modern REPL designed to help the developer by providing a simple but powerful interactive environment, similar to that used in Scala or Ruby.
There are a number of performance and other VM-level enhancements as well. For example, in Java 9, the default garbage collection algorithm has changed – from Parallel in Java 8 and earlier, to G1 (‘Garbage First’) in Java 9.
This is a more modern GC that is designed to work better with larger heaps but, when moving from 8 to 9, some applications will see a difference in GC behaviour.
This change does need proper testing to ensure that customers are not impacted by an application migrating to Java 9.
Alternatively, a VM flag can be used to restore the traditional Parallel collector.
For developers working with cryptography, Java 9 includes changes to the VM to take full advantage of modern processor features and deliver much better performance for cryptographic applications.
One small but potentially useful change is in the internal representation of strings. In Java 8, strings are represented internally as arrays of char.
However, char in Java is a two-byte character, whereas ASCII and most Western text is only one byte per character. This means that roughly half the space taken up by strings is being wasted for many applications.
In Java 9, the option to use ‘Compact Strings’ exists. This uses arrays of byte to represent ASCII or Latin-1 text and saves the wasted space.
A new release plan for Java
Finally, one other major change has arrived with Java: a new Java release model and schedule.
From Java 7 until Java 9, a two-year release cycle was the intended goal. However, in practice, the release train was driven by the delivery of major features. This led to delays of both Java 8 and 9 – in the latter case, a delay of more than a year.
Determined that this situation will not occur again, and conscious of a desire from some developers for faster releases of Java, Oracle has announced a new release plan.
In the new model, a ‘feature’ release of Java will be made every six months. These releases will contain new features, hence the name.
In the old model, new features were restricted to major releases, which meant that developers were waiting, sometimes for years, for new features to arrive.
As well as these feature releases, there will be maintenance and bugfix releases. Every three years, Oracle will produce a long-term support (LTS) release.
The aim is that developers will be able to have the best of both worlds: faster releases for those that want them, but long-term stability and commercial support of Java for the more conservative or slow-moving enterprises.
The new releases, starting with Java 10, will also be fully open-source binaries, built directly from the OpenJDK source repositories, rather than from an opaque Oracle process.
This leaves us with the million-euro question: when should developers migrate their apps?
Every team will have to make their own decision but, for myself, for greenfield development, I might well start using Java 9 straight away if my use case fits.
For an existing app, unless there’s a compelling reason (eg large heaps that are mostly strings and will benefit from Compact Strings, or large heaps where neither Parallel or G1v8 have acceptable performance), then it will probably be more of a wait-and-see approach.
None of the 8/9 migrations I’ve been involved with have been pain-free, so there has to be clear benefit to a project to get me to want to take the pain.
On the whole, Java 9 should probably be seen as necessary engineering work on the platform, rather than anything particularly compelling for the developer.
Despite this, it may well come to be seen as a turning point for the platform that ushers in a new era of faster releases and quicker progress.
Big things are coming for the Java world, but Java 9 is more the signpost that points the way rather than the destination itself.
By Ben Evans
Ben Evans is a technologist and entrepreneur. In partnership with GuruTeam, Evans is delivering his Optimising Java course in Ireland in December 2017. Adapted from his brand new O’Reilly book of the same name, this two-day course is designed for Java developers who want to learn the detailed how and why of Java performance, and how to diagnose and correct performance problems in a systematic and scientific way.