Java 10 – New Features, Code Examples & Support

Java 10 logo

Java (or more accurately JDK) 10 was officially released on 20th March 2018. It includes a total of 12 new features, a full list of which can be found on the OpenJDK project page for JDK 10 , including links to their relevant JDK Enhancement Proposal (JEP) describing each in more detail. This blog post highlights the subset of features that will be of most interest to enterprise Java developers. These include a small number of new Java language features, for which I have also provided some code examples showing how they can be used.

1) New Language Features

There are significantly fewer new features added to the Java language in this release of the JDK compared to recent previous releases such as the new language features added in JDK 8 (including Lambda expressions, and the Streams API) or the new language features added in JDK 9 (which, the module system aside, included e.g. factory methods for Collections; private methods in interfaces). The scarcity of new language features is directly related to JDK 10 being the frst JDK to be released as part of Oracle’s new fixed, time-based release cycle, the aim of which is ensure more frequent and regular releases of Java. (The Java release train now always leaves on time. There are no more delays pending the completion of large features). As a result there was only 6 months for JDK developers to work on new features since JDK 9. Whilst there is less for developers to get excited about in this particular release of the JDK, the long term view is still positive. A pipeline of new language enhancements should build up, and should now be released more quickly.

1.1) Local variable type inference (‘var’)

This is the only major new language feature in JDK 10.

Type inference is the practice of the compiler figuring out the static types of variables and arguments so developers don’t have to type them, resulting in more concise, and in some cases easier to maintain (refactor) code. Prior to J10 there were already a small no. of cases in which Java provided type inference. For example, the diamond operator avoids the need to type generic parameters twice when declaring a collection. The type of the arguments of lambda expressions can also be omitted where no disambiguation is needed. However, it was still the case that when declaring variables, especially intermediate ones of parameterised generic types, it was necessary to repeat the type on the left-hand side of a variable declaration. To address this, JDK 10 adds support for local-variable type inference. This removes the need to specify the type in a local-variable declaration, which is instead replaced with the reserved type (not keyword) ‘var’. The compiler fills in the appropriate type from the variable initializer. For example –

final var countryToCityMap = Map.of(	 	 
 "UK", List.of("London", "Manchester", "Birmingham", "Liverpool"),	 	 
 "Italy", List.of("Rome", "Turin", "Naples", "Milan")	 	 
);	 	 

for (var citiesInCountry : countryToCityMap.entrySet()) {	 	 
 var cities = citiesInCountry.getValue();	 	 
  ...	 	 
}

In J10, ‘var’ can only be used when declaring local variables, and index variables in for-loops. It can NOT be used in other places, including class fields, method (including constructor) params and return types.

1.2) Enhancements to the Standard Library APIs

Some minor enhancements have been made to the Java standard library APIs in JDK 10. Of these, the few that will be of most use in everyday development are outlined below.

Creating Unmodifiable Collections

The java.util.List, Map and Set interfaces have been extended to support creating these types from an immutable copy of a supplied java.util.Collection, using a new static factory named copyOf, e.g. List.copyOf(Collection). The Collection created by these new factory methods have similar properties to those created by the of() static factory methods on the same interface (e.g. List.of()), that were added in Java 9, except that the elements are sourced from a supplied Collection, rather than supplied individual elements. The properties of those collection are described in the class-level Javadoc of each enhanced (List, Map, Set) interface, under the heading “Unmodifiable [List|Set|Map]”.

Accumulate Elements into Unmodifiable Collections

The java.util.stream.Collectors static utility class has been extended to provide methods (e.g. toUnmodifiableList()) that return a java.util.stream.Collector that accumulate the input elements into different types of unmodifiable collection, including List, Set and Map.

java.util.Optional

The Optional class gets a new method, orElseThrow(). If the Optional holds a value it is returned. Otherwise, a NoSuchElementException is thrown. This is identical in behaviour to existing method Optional.get(), and seems only to have been added as a more clearly named alternative. I assume the latter will be deprecated in the future.

I’ve produced a set of easy to run Java code examples for all of the new language features in Java 10 which explain them in more detail and illustrate how they can be used. You can find the code on GitHub.

2) Other Features of Interest to Developers

Beyond the slim pickings of new language features, there are a couple of other features in JDK 10 that will also be of interest to developers.

2.1) Improved Linux (e.g. Docker) Container Awareness

The JVM predates the relatively recent surge in popularity of Linux containers (namespaces, cgroups etc) and their use for application virtualisation. As a result the JVM, like other tools, has historically been lacking and playing catch-up in its support in this area. In particular, the JVM ergonomics, which in the absence of explicit values is responsible for tuning the garbage collector, heap size, and runtime compiler, based on the available resources it detects on the host node, failed to detect and hence respect resource limits applied to containers. Instead it based its default values on the (unconstrained) resources on the underlying host. However, the JVM’s awareness and support of container runtimes has been steadily been improving with the last couple of JDK releases, and with JDK 10, the JVM is now fully container aware.

When running on Linux-based O/S, the JVM will now, by default, detect any hardware resource limits that exist when running in a container, and use those limits, in preference to values returned by the host O/S, when sizing and tuning itself. The information extracted from the container includes the number of CPUs and total memory that have been allocated to the container. The total number of CPUs available to the Java process is calculated from any specified cpu sets, cpu shares or cpu quotas. A few new JVM command line flags have also been added to give greater control (support manual tuning) –

  • -XX:-UseContainerSupport – Can be used to disable the new container awareness, which is on by default, if for any reason you need to revert to previous behaviour of not respecting container resource limits.
  • -XX:ActiveProcessorCount – Overrides automatic CPU detection. Supports explicitly specifying (overriding) how many processors a JVM running in a container (or on a host) will use.
  • -XX:InitialRAMPercentage; -XX:MaxRAMPercentage; -XX:MinRAMPercentage – These 3 new JVM options have been added to provide more fine grained control over the amount of system memory that will be used for the Java Heap.

The experimental JVM flag -XX:+UseCGroupMemoryLimitForHeap, which was added in JDK9 (and backported to JDK 8), to respect any RAM limits specified for the container when calculating the max available JVM heap size, having been superseded by the above changes in JDK 10, has been deprecated, and will be removed in JDK 11.

For confirmation of the above see Oracle’s JDK 10 Release Notes > Other Notes > Java Improvements for Docker Containers, which also contains links to the relevant tickets (‘bug fixes’) detailing the work.

2.2) Security – OpenJDK Includes a Default Set of Root CA SSL Certs

In JDK 9, the OpenJDK binary distribution did not ship with any SSL certs for root Certification Authority (CA) – the cacerts keystore was empty. This prevented TLS connections from working out of the box, requiring users to set the javax.net.ssl.trustStore System Property to use a different keystore. In OpenJDK 10, this is no longer necessary. The cacerts keystore is now populated with a set of root certificates issued by the CAs of Oracle’s Java SE Root CA Program. (This change has been made as part of the broader work Oracle is undertaking to ensure that OpenJDK binaries and Oracle JDK binaries are functionally equivalent).

3) Tools

Support for running Gradle builds using JDK10 was added in Gradle 4.7, which was released ~04/2018. See the Gradle release notes.

4) Support Considerations

Java (SE) 10 is a not a Long Term Support (LTS) release. This means that six months from its release (around the end of Sept, when Java 11 is scheduled for release) Java 10 will be considered end-of-life by Oracle. There will be no further free maintenance and security updates, and Oracle will also not be offering any further support, even if you’re willing to pay. (This was the same for Java 9, which on the release of Java 10, is itself now end-of-life).

Given this situation, you should think twice before upgrading your apps in production to Java 10. If security patches and support for Java is important to your business, then you have a choice of either committing to upgrading to the new release of Java every 6 months, or else only upgrade your production environments to those Java releases (8, 11, 17, …) for which extended (free or paid) support will be available. As I’ve previously stated, my personal advice is that unless there a feature is introduced in a non-LTS release of Java that is absolutely essential to your business, then I would stick to the LTS releases in production, and just trial the upgrades to interim releases in test in the meantime. Personally I’m looking to upgrading from Java 8 to Java 11 in production.

I hope you found this blog post useful. To get more insight into the new Java language features introduced in JDK 10 see my code examples on GitHub.

Thanks.

Advertisements

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s