Java 9 New Features

Java SE 9 was released in September 2017 with a rich feature set. 

The full list of new features in JDK 9 can be found here:

In this tutorial, we will look at some of these new features and examine some of them.

1. Modular System – Jigsaw Project

The Java platform is modularized into numerous modules in Java 9. 
Developers can now create custom runtimes consisitng of the only modules needed by the target application.
We already examine the outlines of Jigsaw project in the following article:

2. JEP 223: New Version-String Scheme

Java version-string is a string format that contains information about the Java version.
Prior to Jdk 9, it was hard to identify version information from JDK version-string.
With JEP 223, version-string was rearranged with a more systematic naming scheme.

Java version-string consists of major, minor, security and patch version numbers of Java releases.



When a major changes occur in the JDK, then $MAJOR version number is increased.
A major change comes with new features to the JDK specification as happened in Java 8 to Java 9.


Minor releases come with bug fixes and/or modifications to standard API.
If an update is released then minor portion of the version string increases, for example from 9.0 to 9.1.


If a security update is released, then the security poriton of the version string increases, for example from 9.1.1 to 9.1.2.


Patch is increased for builds containing security and bug fixes for high-priority customers.


- Each time the $PATCH version number is reset to zero if any $SECURITY, $MINOR, or $MAJOR version numbers are incremented.
- The $MINOR and $SECURITY version numbers are set to zero, if the $MAJOR version number is incremented. 
- However, when the $MINOR version number is incremented, the subsequent $SECURITY version number need not be set to zero.


java -version

Major version number 9

Minor version number 0
Security version number 1
Pre-released information Optional.empty
Build Number Optional[11]


3. JEP 269: Convenience Factory Methods for Collections

JEP 269 defines new APIs to ease creating instances of collections.

Before JEP 269:

List<Point> myList = new ArrayList<>();
myList.add(new Point(1, 1));
myList.add(new Point(2, 2));
myList.add(new Point(3, 3));
myList = Collections.unmodifiableList(myList);

With JEP 269:

List<Point> list = List.of(new Point(1, 1), new Point(2, 2), new Point(3, 3));

Map map = Map.of("One", 1, "Two", 2, "Three", 3);


4. Stream API Enhancements

4.1 Stream.iterate

Stream.iterate in Java 8 creates an infinite stream.
Stream.iterate(initial value, next value)

Stream.iterate(0, n -> n + 1)
        .forEach(x -> System.out.println(x));

JDK 9 overloads iterate with three parameters that replicate the standard for loop syntax as a stream.
For example, Stream.iterate(0, i -> i < 5, i -> i + 1) gives you a stream of integers from 0 to 4.

Stream.iterate(initial value, stopper predicate, next value)

Stream.iterate(1, n -> n < 20 , n -> n * 2)
        .forEach(x -> System.out.println(x))

4.2 takeWhile

Stream.iterate("", s -> s + "t")
        .takeWhile(s -> s.length() < 10)
        .reduce((first, second) -> second) //find last
        .ifPresent(s -> System.out.println(s));

4.3 dropWhile

dropWhile removes elements while the given predicate returns true.

System.out.print("when ordered:");
      .dropWhile(x -> x < 4)
      .forEach(a -> System.out.print(" " + a));
System.out.print("when unordered:");
      .dropWhile(x -> x < 4)
      .forEach(a -> System.out.print(" " + a));

4.4 Extracting null values - ofNullable

Extracting null values in Java 8:

Stream.of("1", "2", null, "4")
      .flatMap(s -> s != null ? Stream.of(s) : Stream.empty())
      .forEach(s -> System.out.print(s));

Extracting null values in Java 9 - ofNullable:

Stream.of("1", "2", null, "4")
      .flatMap(s -> Stream.ofNullable(s))
      .forEach(s -> System.out.print(s));

5. Optional Class Enhancements

5.1 Default value

Default value with [orElseGet] in Java 8; returns unwrapped value:

String nullName = null;
String name = Optional.ofNullable(nullName).orElseGet(() -> "test");
assertEquals("test", name);

Java 9 [or] method; returns Optional in case of null; useful when you want to ensure that you always have an Optional.

Optional defaultValue = Optional.of("test");      
Optional name = Optional.ofNullable((String) null).or(() -> defaultValue);
assertEquals(defaultValue.get(), name.get());

5.2 ifPresentOrElse  

ifPresentOrElse(Consumer action, Runnable emptyAction)
Similar to ifPresent, but if there is no value, it executes the emptyAction.

          v -> successCounter.incrementAndGet(),     //ifPresent 
          onEmptyOptionalCounter::incrementAndGet);  //orElse

5.3 Optional as a Stream

stream() method on Optional returns a stream of zero or one elements.

Optional value = Optional.of("a");
List collect =;

6. JEP 213: Milling Project Coin

Allow effectively-final variables to be used as resources in the try-with-resources statement.

Along with Java 7, resources can be closed automatically by using try-with-resources. However, there had been a problem with that closing a resource defined outside of try block is out of scope of this feature.

StringWriter sw = new StringWriter();  
try(PrintWriter pw = new PrintWriter(sw)) {
} finally {
     try {
     } catch (IOException e) {

With Java 9, this is resolved and the code above can be rewritten as:

StringWriter sw = new StringWriter();  
try(sw; PrintWriter pw = new PrintWriter(sw)) {

7. Interface Changes

With Java 9, there has been several changes to interfaces also. Let's look at these changes historically:

In Java SE 7 or earlier versions;
  - Constant variables
  - Abstract methods

static final String TEST_CONSTANT = "TEST CONSTANT";
Integer sum(Integer a, Integer b);
abstract Integer multiply(Integer a, Integer b);

Along with Java 8;
  - Constant variables
  - Abstract methods
  - Default methods
  - Static methods

default Integer divide(Integer a, Integer b) {
    return a / b;
static Integer increment(Integer a) {
    return a + 1;

Along with Java 9;
  - Constant variables
  - Abstract methods
  - Default methods
  - Static methods
  - Private methods
  - Private static methods

private void log(String log) {
private static void debug(String log) {

8. JEP 248: Make G1 the Default Garbage Collector

Switching to a low-pause collector such as G1 should provide a better overall experience, for most users, than a throughput-oriented collector such as the Parallel GC, which is formerly the default. Therefore, G1 is made the default garbage collector along with Java 9.



The Convergence of OpenJDK and the Oracle JDK

It's Time For Faster Releases

Project Jigsaw