Java 9 Features and Enhancements

Java 9 is bringing lots of new enhancements which are going to affect your programming style and habit, in big way. The biggest change is the modularization of Java. It’s another big change after Lambdas in Java 8. In this article, I am listing down changes which will be part of JDK 9 release.

What is new in Java 9

Java platform module system
Interface Private Methods
HTTP 2 Client
JShell - REPL Tool
Platform and JVM Logging
Process API Updates
Collection API Updates
Stream API Improvements
Multi-Release JAR Files
@Deprecated Tag Changes
Stack Walking
Java Docs Updates
Miscellaneous Other Features

Java platform module system

JPMS (Java Platform Module System) is the core highlight of new Java 9 release. It is also known as Project Jigshaw. A module is new construct like we already have packages. An application, developed using new modular programming, can be seen as collection of interacting modules with a well-defined boundaries and dependencies between those modules.

The JPMS consists of providing support for writing modular applications as well as modularizing the JDK source code as well. JDK 9 is coming with around 92 modules (changes are possible in GA release). Java 9 Module System has a “java.base” Module. It’s known as Base Module. It’s an Independent module and does NOT dependent on any other modules. By default, all other modules are dependent on “java.base”.

In java modular programming-

  1. A module is typically just a jar file that has a module-info.class file at the root.
  2. To use a module, include the jar file into modulepath instead of the classpath. A modular jar file added to classpath is normal jar file and module-info.class file will be ignored.

Typical module-info.java classes looks like this:

module helloworld {
    exports com.howtodoinjava.demo;
}
 
module test {
    requires helloworld;
}

Read More: Java 9 Modules Tutorial

Interface Private Methods

Java 8 allowed you to write default methods in interfaces, and it was widely appreciated feature. So after this, interfaces only lack few things and only non-private methods was one of them. Java 9 onward, you are allowed to include private methods in interfaces.

These private methods will improve code re-usability inside interfaces. Foe example, if two default methods needed to share code, a private interface method would allow them to do so, but without exposing that private method to it’s implementing classes.

Using private methods in interfaces have four rules :

  1. Private interface method cannot be abstract.
  2. Private method can be used only inside interface.
  3. Private static method can be used inside other static and non-static interface methods.
  4. Private non-static methods cannot be used inside private static methods.

An example of using private methods in interfaces –

public interface CustomCalculator 
{
    default int addEvenNumbers(int... nums) {
        return add(n -> n % 2 == 0, nums);
    }
 
    default int addOddNumbers(int... nums) {
        return add(n -> n % 2 != 0, nums);
    }
 
    private int add(IntPredicate predicate, int... nums) { 
        return IntStream.of(nums)
                .filter(predicate)
                .sum();
    }
}

Java 9 – Private Methods in Interface

HTTP/2 Client

HTTP/1.1 client was released on 1997. A lot has changed since. So for Java 9 a new API been introduced that is cleaner and clearer to use and which also adds support for HTTP/2. New API uses 3 major classes i.e. HttpClient, HttpRequest and HttpResponse.

To make a request, it is as simple as getting your client, building a request and sending it as shown below.

HttpClient httpClient = HttpClient.newHttpClient(); 
HttpRequest httpRequest = HttpRequest.newBuilder().uri(new URI("//howtodoinjava.com/")).GET().build(); 
HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandler.asString()); 
System.out.println( httpResponse.body() ); 

Above code looks much cleaner and readable.

New API also support Async HTTP requests using httpClient.sendAsync() method. It returns CompletableFuture object which can be used to determine whether the request has been completed or not. It also provide you access to the HttpResponse once request is completed. Best part is that if you desire you can even cancel the request before it completes. e.g.

if(httpResponse.isDone()) {
    System.out.println(httpResponse.get().statusCode());
    System.out.println(httpResponse.get().body());
} else {
    httpResponse.cancel(true);
}

JShell – REPL Tool

JShell is new command line interactive tool shipped with JDK 9 distribution [JEP 222] to evaluate declarations, statements and expressions written in Java. JShell allows us to execute Java code snippets and get immediate results without having to create a solution or project.

Jshell is much like what we have command window in linux OS. Difference is that JShell is Java specific. It has lots of other capabilities, other than executing simple code snippets. e.g.

  • Launch inbuilt code editor in separate window
  • Launch code editor of your choice in separate window
  • Execute code when Save operation happen in these external editors
  • Load pre-written classes from file system

Java 9 JShell Tutorial

Platform and JVM Logging

JDK 9 has improved logging in platform classes (JDK classes) and JVM components, through a new loging API. It lets you specify a logging framework of your choice (e.g. Log4J2) as logging backend for logging messages from JDK classes. There are few things you should know about this API:

  1. The API is meant to be used by the classes in the JDK, not by application classes.
  2. For your application code, you will continue using other logging APIs as before.
  3. The API does not let you configure the logger programmatically.

The API consists of the following:

  • A service interface, java.lang.System.LoggerFinder, which is an abstract static class
  • An interface, java.lang.System.Logger, which provides the logging API
  • An overloaded method getLogger() in the java.lang.System class, which returns a logger instance.

JDK 9 also added a new command-line option, -Xlog , that gives you a single point of access to all messages logged from all classes of the JVM. The following is the syntax to use the -Xlog option:

-Xlog[:][:[][:[][:]]]

All options are optional. If a preceding part in -Xlog is missing, you must use a colon for that part. For example, -Xlog::stderr indicates that all parts are defaulted, output wich is set as stderr.

I will cover this topic in deep, in a separate post.

Process API Updates

Prior to Java 5, the only way to spawn a new process was to use the Runtime.getRuntime().exec() method. Then in Java 5, ProcessBuilder API was introduced which supported a cleaner way of spawning new processes. Now Java 9 is adding a new way of getting information about current and any spawned process.

To get information of any process, now you should use java.lang.ProcessHandle.Info interface. This interface can be useful in getting lots of information e.g.

  • the command used to start the process
  • the arguments of the command
  • time instant when the process was started
  • total time spent by it and the user who created it
ProcessHandle processHandle = ProcessHandle.current();
ProcessHandle.Info processInfo = processHandle.info();

System.out.println( processHandle.getPid() );
System.out.println( processInfo.arguments().isPresent() );
System.out.println( pprocessInfo.command().isPresent() );
System.out.println( processInfo.command().get().contains("java") );
System.out.println( processInfo.startInstant().isPresent() );

To get the information of a new spawned process, use process.toHandle() method to get ProcessHandle instance. Rest all of things are as above.

String javaPrompt = ProcessUtils.getJavaCmd().getAbsolutePath();
ProcessBuilder processBuilder = new ProcessBuilder(javaPrompt, "-version");
Process process = processBuilder.inheritIO().start();
ProcessHandle processHandle = process.toHandle();

Also use ProcessHandle.allProcesses() to get a stream of ProcessHandle of all processes available in system.

To get the list of all child processes (direct as well as n-level deep), use children() and descendants() method.

Stream<ProcessHandle> children    = ProcessHandle.current().children();
Stream<ProcessHandle> descendants = ProcessHandle.current().descendants();

Collection API Updates

Since Java 9, you can create immutable collections such as immutable list, immutable set and immutable map using new factory methods. e.g.

import java.util.List;
 
public class ImmutableCollections 
{
    public static void main(String[] args) 
    {
        List<String> namesList = List.of("Lokesh", "Amit", "John");

        Set<String> namesSet = Set.of("Lokesh", "Amit", "John");

        Map<String, String> namesMap = Map.ofEntries(
					                Map.entry("1", "Lokesh"),
					                Map.entry("2", "Amit"),
					                Map.entry("3", "Brian"));
    }
}

Java 9 Collections API Improvements

Stream API Improvements

Java 9 has introduced two new methods to interact with Streams i.e. takeWhile / dropWhile methods. Additionally, it has added two overloaded methods i.e. ofNullable and iterate methods.

The new methods takeWhile and dropWhile allow you to get portions of a stream based on a predicate.

  1. On an ordered stream, takeWhile returns the “longest prefix” of elements taken from the stream that match the given predicate, starting at the beginning of the stream. dropWhile returns the remaining items which were not matched by takeWhile.
  2. On an un-ordered stream, takeWhile returns a subset of the stream’s elements that match the given predicate (but not all), starting at the beginning of the stream. dropWhile returns remaining stream elements after dropping subset of elements that match the given predicate.

Similarily, till Java 8, you cannot have null value in a stream. It would have caused NullPointerException. Since Java 9, Stream.ofNullable() method lets you create a single-element stream which wraps a value if not null, or is an empty stream otherwise. Technically, Stream.ofNullable() is very similar to null condition check, when talking in context of stream API.

Java 9 Stream API Improvements

Multi-Release JAR Files

This enhancement is related to how you package application classes in jar files. Previously, you had to package all classes into a jar file and drop in the classpath of the another application, which wish to use it.

Using multi-release feature, now a jar can contains different versions of a class – compatible to different JDK releases. The information regarding different versions of a class, and in which JDK version which class shall be picked up by class loaded, is stored in MANIFEST.MF file. In this case, MANIFEST.MF file includes the entry Multi-Release: true in its main section.

Furthermore, META-INF contains a versions subdirectory whose integer-named subdirectories — starting with 9 (for Java 9) — store version-specific class and resource files. e.g.

JAR content root
  A.class
  B.class
  C.class
  D.class
  META-INF
     MANIFEST.MF
     versions
        9
           A.class
           B.class

Let’s assume that in JDK 10, A.class is updated to leverage some Java 10 features, then this Jar file can be updated like this:

JAR content root
  A.class
  B.class
  C.class
  D.class
  META-INF
     MANIFEST.MF
     versions
        9
           A.class
           B.class
        10
           A.class

It looks really promising step to solve the dependency hell often seen in large application where jars with different versions are not compatible with each other. This feature can be a big help to tackle those scenarios.

@Deprecated Tag Changes

From Java 9, @Deprecated annotation will have two attributes i.e. forRemoval and since.

  1. forRemoval – Indicates whether the annotated element is subject to removal in a future version.
  2. since – It returns the version in which the annotated element became deprecated.

It is strongly recommended that the reason for deprecating a program element be explained in the documentation, using the @deprecated javadoc tag. The documentation should also suggest and link to a recommended replacement API, if applicable. A replacement API often has subtly different semantics, so such issues should be discussed as well.

Stack Walking

The stack is a Last-In-First-Out (LIFO) data structure. At JVM level, a stack stores frames. A new frame is created and pushed to the top of the stack each time a method is invoked. A frame is destroyed (popped out of stack) when the method invocation completes. Each frame on a stack contains its own array of local variables, as well as its own operand stack, return value, and reference to the runtime constant pool of the current method’s class.

In a given thread, only one frame is active at any point. The active frame is known as the current frame and its method is known as the current method . [Read More]

Till Java 8, StackTraceElement represents a stack frame. To get complete stack, you had to use Thread.getStackTrace() and Throwable.getStackTrace(). It returned an array of StackTraceElement which you can iterate to get required information.

In Java 9, a new class StackWalker has been introduced. The class provides easy and efficient stack walking using sequential stream of stack frames for the current thread. The StackWalker class is very efficient because it evaluates the stack frames lazily.

// Prints the details of all stack frames of the current thread

StackWalker.getInstance().forEach(System.out::println);

There are other lots of things you can do with this stream, which we will cover in some other decdicated post.

Java Docs Updates

Java 9 enhances the javadoc tool to generate HTML5 markup. It currently generates pages in HTML 4.01.

In order to generate a HTML5 Javadoc, the parameter -html5 needs to go in the command line arguments. To generate the document on the command line, you would run:

javadoc [options] [packagenames] [sourcefiles] [@files]

Using HTML5 confers the benefits of the easier HTML5 structure. It also implements the WAI-ARIA standard for accessibility. This aims to make it easier for people with physical or visual impairments to access javadocs pages using tools such as screen readers.

JEP 225 gives the ability to search a javadoc for program elements and tagged words and phrases.

The following will be indexed and searchable:

  • Declared names of modules
  • Packages
  • Types and members
  • The simple name of method parameter types

This is implemented client side, with a new search.js Javascript file, along with indexes generated when the javadoc is generated. A search box is available on the generated HTML5 API pages.

Please note that Search option will be added by default, but can be turned off with the argument: -noindex.

Miscellaneous Other Features

There are other features as well in Java 9, which I am listing down here for quick reference. We will discuss all these features in coming posts.

  • Reactive Streams API
  • GC (Garbage Collector) Improvements
  • Filter Incoming Serialization Data
  • Deprecate the Applet API
  • Indify String Concatenation
  • Enhanced Method Handles
  • Compact Strings
  • Parser API for Nashorn
Java 9 is scheduled to release on 2017/09/21. For latest changes, follow this link.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

1 thought on “Java 9 Features and Enhancements”

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.