JDK 9 New Features

  1. "What's New in Oracle JDK 9" @
  2. "JDK 9 release notes" @
  3. OpenJDK's JDK 9 @


JDK 9 comes with these big new features (plus some minor new features and enhancements):

  1. Java Module System (Project Jigsaw)
  2. JDK 9 REPL (Read Evaluate Print Loop) - jshell
  3. Some language changes, e.g., JEP 213: Milling Project Coin.

JDK 9 Java Module System - Project Jigsaw

See "Java Module System".

JDK 9 REPL - jshell

JDK 9 introduces a new tool called jshell to support REPL (Read-Evaluate-Print-Loop). It is used to execute and test any Java constructs like class, interface, enum, object, statements etc. For example,

> jshell
|  Welcome to JShell -- Version 10.0.1
|  For an introduction type: /help intro

jshell> int i = 123
i ==> 123

jshell> i + 456
$2 ==> 579

jshell> System.out.println("hello")

jshell> for (var i = 0; i < 3; ++i)
   ...>    System.out.println(i*i)

jshell> /exit
|  Goodbye

JDK 9 New Language Features

Reference: Java Language Updates Java SE 9 @


JDK 9 introduces a few new language features, under "JEP 213: Milling Project Coin".

private and private static methods in the interface

Prior to Java 8, an interface can have only two kinds of entities:

  1. public static final variables (constants)
  2. public abstract methods: method signature only without implementation.

You need to use an abstract class if you have non-abstract methods with implementations.

Java 8 introduces public default and public static methods into the interface. You could provide implementations in these methods.

JDK 9 supports private methods and private static methods. In JDK 9, an interface can contains six kinds of entities:

  1. public static final variables (constant)
  2. public abstract methods
  3. public default methods
  4. public static methods
  5. private methods: meant for helper method accessible wtihin the current interface only, so as to remove redundant codes. Not inherited by its subclasses and cannot be overridden.
  6. private static methods: class helper method accessible within the current interface only.

try-with-resources Improvements

Before Java 7, you need to use a try-catch-finally construct to manage resource, and manually close all resource in the finally. Java 7 introduces a new try-with-resources construct which automatically closes all resources at the end of the statement. Read HERE.

If you already have a resource as a final or "effectively final" variable, you can use that variable in a try(resources) clause without declaring a new variable. An "effectively final" variable is one whose value is never changed after it is initialized. For example,


// Copy from one file to another file line by line.
// Java 7 has a try-with-resources statement, which ensures that
//   each resource opened in try(resources) is closed at the end of the statement.
public class FileCopyJava9 {
   public static void main(String[] args) throws IOException {
      BufferedReader src  = new BufferedReader(new FileReader("in.txt"));
      BufferedWriter dest = new BufferedWriter(new FileWriter("out.txt"));

      try (src; dest) {   // This is permitted in JDK 9
         String line;
         while ((line = src.readLine()) != null) {
      } catch (IOException ex) {
      // src and dest automatically close.
      // No need for finally to explicitly close the resources.

Before JDK 9, you need to create new variables:

try (BufferedReader src1 = src;
     BufferedWriter dest1 = dest) {

[TODO] Write a better example.

Other Minor Language Changes

@SafeVargs annotation is allowed on private instance methods

The @SafeVarargs annotation can be applied only to methods that cannot be overridden. These include static methods, final instance methods, and, new in JDK 9, private instance methods.

Allow the diamond operator with anonymous inner classes

In JDK 9, as long as the inferred type is denotable, you can use the diamond operator <> when you create an anonymous inner class.

Removal of the underscore from the set of legal identifier names

If you use the underscore character ("_") as an identifier, your source code can no longer be compiled.

JDK 9 Library Changes

Convenience Factory Methods for Collections (JEP 269)


Prior to JDK 9, creating a small, unmodifiable collection of List, Set, or Map involves constructing it, storing it in a local variable, and invoking add() on it several times, and then wrapping it. For example,

List lst1 = new ArrayList<>();  // construct and store in a local variable
lst1.add("apple1");             // several add()'s
lst1 = Collections.unmodifiableList(lst1);  // wrap it

Alternatively, you could populate a collection using a "copy constructor" from another collection, for example,

List lst2 = Collections.unmodifiableList(
   new ArrayList<>(Arrays.asList("apple2", "orange2", "banana2")));
   // Using the "copy constructor" of ArrayList

Another alternative is to use the so-called "double brace" technique, which uses the instance-initializer construct in an anonymous inner class, for example,

List lst3 = Collections.unmodifiableList(new ArrayList<>() {{
   add("apple3"); add("orange3"); add("banana3");

You could also use the Java 8's Stream API to construct small collections, by combining stream factory methods and collectors, for example,

List lst4 = Collections.unmodifiableList(
   Stream.of("apple4", "orange4", "banana4").collect(Collectors.toList()));
JDK 9 New Features

JDK 9 provides a static factory method called of() in the List, Set, and Map interfaces to simplify creation of unmodifiable instances of these collections. We can write:

List<String> lst = List.of("apple", "orange", "banana");
Set<String> set = Set.of("apple", "orange", "banana");
Map<Integer, String> map = Map.of(1, "apple", 2, "orange", 3, "banana");

For List and Set, the factory methods of() are heavily overloaded for zero to ten elements, plus arbitrary number of elements, as follows:

// List interface's factory method to return an immutable list
static <E> List<E> of​(E... elements)  // an arbitrary number of elements with varargs
static <E> List<E> of​()               // zero elements
static <E> List<E> of​(E e1)           // one element (fixed)
static <E> List<E> of​(E e1, E e2)     // two elements
static <E> List<E> of​(E e1, E e2, E e3)  // three elements
static <E> List<E> of​(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)  // ten elements

// Set interface has a similar set of overloaded methods

The of() includes varargs overloads, so that there is no limit on the size. It is tuned for smaller sizes with fixed-argument overloads for up to ten of elements. While this introduces some clutter in the API, it avoids array allocation, initialization, and garbage collection overhead that is incurred by varargs calls.

For Map, a set of fixed-argument methods are provided for zero to ten elements:

static <K,V> Map<K,V> of​()  // zero elements
static <K,V> Map<K,V> of​(K k1, V v1)  // one element
static <K,V> Map<K,V> of​(K k1, V v1, K k2, V v2)  // two elements
static <K,V> Map<K,V> of​(K k1, V v1, K k2, V v2, 
      K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6,
      K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10)  // ten elements

To support arbitrary number of elements, the Map interface provides a static method called ofEntries(), which takes argument of Map.Entry objects, as follows:

static <K,V> Map<K,V> ofEntries​(Map.Entry<? extends K,? extends V>... entries)

Another staitc method called entry() is also provided to create a Map.Entry object:

static <K,V> Map.Entry<K,V> entry​(K k, V v)  // Returns an immutable Map.Entry containing the given key and value.

For examples,

Map<Integer, String> m1 = Map.of(1, "apple1", 2, "orange2", 3, "banana3");  // three elements (fixed)
Map<Integer, String> m2 = Map.ofEntries(  // arbitrary elements
      Map.entry(1, "apple2"),
      Map.entry(2, "orange2"),
      Map.entry(3, "banana2"));

Note that interface's static methods are not inherited, so it will not be possible to invoke them via an implementing subclasses, nor via an instance of the interface type.


Process API Improvements

Added two new interfaces in Process API: java.lang.ProcessHandle and

CompletableFuture API Improvements

Support delays and timeouts, add some utility methods and better sub-classing.

Reactive Streams

JDK 9 Reactive Streams API is a Publish/Subscribe Framework to implement asynchronous, scalable and parallel applications. JDK 9 introduces: java.util.concurrent.Flow, java.util.concurrent.Flow.Publisher, java.util.concurrent.Flow.Subscriber, java.util.concurrent.Flow.Processor.

Optional Class Improvements

JDK 9 added some useful new methods to java.util.Optional class, such as stream().

Stream API Improvements

JDK 9 added four useful new default methods to java.util.Stream interface: dropWhile(), takeWhile().

The takeWhile() takes a predicate as an argument and returns a Stream of subset of the given Stream values until that predicate returns false for first time. If first value does NOT satisfy that predicate, it just returns an empty Stream. For example,

Stream.of(1,2,3,4,5,6,7,8,9,10).takeWhile(i -> i < 5)

JDK 9 Other New Features

Enhanced @Deprecated annotation

Prior to JDK 9, @Deprecated annotation is just a Marker interface without any methods. JDK 9 enhances @Deprecated annotation to provide more information about deprecated API and also provide a tool jdeprscan to analyse an application’s static usage of deprecated APIs. Two methods were added: forRemoval() and since() to serve this information.

HTTP2 Client

HTTP/2 is an improvement over HTTP/1.1:

  • In HTTP/1.1, we cannot have more than six connections open at a time, so every request has to wait for the others to complete. HTTP/2 can send multiple requests for data in parallel over a single TCP connection, known as "HTTP/2 Multiplexing".
  • In HTTP/1.1, every request sent to the server will have the header's additional data, which increases bandwidth. This can be eliminated in HTTP/2.0 by having headers packed into one compressed block that will be sent as a unit, known as "HTTP/2 Header Compression".
  • In an HTTP/1.1, an HTML page is sent to the browser. The browser has to parse it and decide which assets are required, then request those assets from the server. This can be eliminated by "Server Push" in HTTP/2. It allows servers to push responses proactively to the client instead of waiting for the new request to process.
  • Text is replaced by Binary in HTTP/2.
  • Domain sharding and asset concatenation are no longer needed with HTTP/2.

JDK 9 introduces new HTTP2 Client API (under JEP 110: HTTP/2 Client (Incubator)). It supports both HTTP/1.1 and HTTP/2 protocols. It supports both synchronous (blocking mode) and asynchronous modes (using WebSocket API).

Multi-Resolution Image API

JDK 9 added an interface MultiResolutionImage in java.awt.image package, which encapsulates a set of images with different height and widths.

  • GC (Garbage Collector) Improvements
  • Stack-Walking API
  • Filter Incoming Serialization Data
  • Deprecate the Applet API (JEP 289: Deprecate the Applet API): The Applet API, which is rapidly becoming irrelevant as web-browser vendors remove support for Java browser plug-ins. JDK 9 marked @Deprecated(since="9") for applet classes, and removed appletviewer tool. Developer should use alternative technologies such as Java Web Start or installable applications.
  • Indify String Concatenation
  • Enhanced Method Handles
  • Java Platform Logging API and Service
  • Compact Strings
  • Parser API for Nashorn
  • Javadoc Search
  • HTML5 Javadoc