The Ultimate Guide to Java 9

After some months of delays, Java 9 is coming ! Java 9 is attended for general availability On March 23, 2017. In that article, you’re going to discover the major new features expected in Java 9. Don’t hesitate to leave me some comments if I forgot some important things.

Main Features

  • Java Platform Module System — JSR 376
  • Process API Updates — JEP 102
  • HTTP 2 Client — JEP 110
  • JShell : The Java Shell — JEP 222
  • Multi-Resolution Images API — JEP 251
  • Stack-Walking API — JEP 259
  • Platform Logging API and Service — JEP 264
  • Reactive Streams — JEP 266
  • Platform-Specific Desktop Features — JEP 272
  • Deserialization Filter — JEP 290
  • XML Catalogs — JEP 268
  • Parser API for Nashorn — JEP 236
  • Language Changes — JEP 213
  • Extension to Existing APIs
  • Some Low Level APIs
  • Applet API deprecation — JEP 289

You can discover all the new features expected in Java 9 in video too :

Java Platform Module System — JSR 376

The Java Platform Module System (JPMS) is the biggest part of Java 9. Specific goals of the module system are :

  • Reliable configuration
  • Strong encapsulation

It will benefit application developers, library developers and implementors of the Java SE Platform. An awesome read to start with JPMS :

http://openjdk.java.net/projects/jigsaw/spec/sotms/

The JDK is now entirely modular. Great step forward ! Example of a module with dependencies (requires and exports) :

module com.foo.bar {
requires org.baz.qux;
exports com.foo.bar.alpha;
exports com.foot.bar.beta;
}

Process API Updates — JEP 102

Goal : Improve the API for controlling and managing OS processes

Motivation : The limitations of the current API often force developers to resort to native code.

The design of this API needs to accommodate possible deployment on smaller devices with different OS models. The new ProcessHandle class makes it more convenient to interact with processes and process trees. Get the PID of the current Process :

private static int getOwnProcessID() {
return ProcessHandle.current().getPid();
}

List all processes on your OS :

ProcessHandle.allProcesses().forEach(h -> printInfo(h));
// ...
public void printInfo(ProcessHandle pHandle){
System.out.println("PID : " + pHandle.info().getPid();
System.out.println("Path : " + pHandle.info().command().orElse("-");
// …
}

The new ProcessBuilder class makes is very easy to build processes and pipelines. Call a ls command then pipe the results into a grep :

ProcessBuilder ls = new ProcessBuilder()
.command("ls")
.directory(Paths.get("/home/ssaurel/tmp").toFile());
ProcessBuilder grepPdf = new ProcessBuilder()
.command("grep", "pdf")
.redirectOutput(Redirect.INHERIT);
List<Process> lsThenGrep = ProcessBuilder
.startPipeline(asList(ls, grepPdf));

HTTP 2 Client — JEP 110

Define a new HTTP Client API implementing HTTP/2 and WebSocket, an can replace the legacy HttpURLConnection API that has numerous problems :

  • Designed with multiple procotols in mind
  • API target HTTP/1.1
  • Too abstract
  • Hard to use
  • Works in blocking mode only

Create and handle a simple HTTP request :

HttpResponse response = HttpRequest
.create(new URI("http://www.ssaurel.com"))
.body(noBody())
.GET().send();
int responseCode = response.responseCode();
String responseBody = response.body(asString());
System.out.println(responseBody);

Make an asynchronous call with the new API :

HttpRequest req = HttpRequest
.create(new URI("http://www.ssaurel.com"))
.body(noBody())
.GET();
CompletableFuture<HttpResponse> aResp = req.sendAsync();
Thread.sleep(10);
if (!aResp.isDone()) {
aResp.cancel(true);
System.out.println("Failed to reply in 10 seconds ...");
return;
}
HttpResponse response = aResp.get();

The Java Shell — JEP 222

Goal is to provide an interactive tool to evaluate declarations, statements, expressions of the Java language with and API letting other applications to leverage this functionality. With Java 9, the JDK will have its own Read-Eval-Print-Loop (REPL) tool !
Evaluate and print expressions :

-> 3 * (4 + 5)
| Expression value is: 27
| assigned to temporary variable $1 of type int
-> System.out.println($1);
27

Define some variables and list them :

-> String s = "Sylvain Saurel"
| Added variable s of type String with initial value "Sylvain Saurel"
-> /vars
| int $1 = 27
| String s = "Sylvain Saurel"

You can even define classes :

-> class Pet {}
| Added class Pet
-> class Cat extends Pet {}
| Added class Cat

Multi-Resolution Images API — JEP 251

Goal is to define a multi-resolution images API so that images with resolution variants can easily be manipulated and displayed by developers.

Basic operations on a multi-resolution image :

  • Retrieve resolution-specific image variant based on a given DPI metric and set of image transformations
  • Retrieve all the variants in the image

MultiResolutionImage interface with a BaseMultiResolutionImage implementation provided :

package java.awt.image;
public interface MultiResolutionImage {
Image getResolutionVariant(float destImageWidth, float destImageHeight);
public List<Image> getResolutionVariants();
}

Stack-Walking API — JEP 259

Goal : Define an efficient standard API for stack walking that allows easy filtering of, and lazy access to, the information in stack traces

Motivation : Existing APIs require the VM to eagerly capture a snapshot of the entire stack and they return information representing the entire stack. It’s an heavy operation ! The Stack-Walking API wants to solve this problem.

Make a couple of calls and then walk the stack until we find the frame that belongs to a specific method :

public static void main(String[] args) { one(); }
static void one() { two(); }
static void two() { three(); }
static void three() {
String line = StackWalker.getInstance().walk(StackWalking::walk);
System.out.println(line);
}
private static String walk(Stream<StackFrame> stackFrameStream) {
return stackFrameStream
.filter(frame -> frame.getMethodName().contains("one"))
.findFirst()
.map(frame -> "Line " + frame.getLineNumber())
.orElse("Unknown line");
}

Platform Logging API and Service — JEP 264

Define a minimal logging API which platform classes can use to log messages, together with a service interface for consumers of those messages.

The JDK classes now pipe messages through the new interface Logger (either directly or on a detour through sun.util.logging.PlatformLogger) — instances of which are provided by a single LoggerFinder.

Reactive Streams — JEP 266

JEP 266 aims to offer an interoperable Reactive Streams publish-subscribe framework, enhancements to the CompletableFuture API and various other improvements.

JDK will provide a minimal set of interfaces that capture the heart of asynchronous publication and subscription mechanism with Publisher, Subscriber and Subscription objects.

Platform-Specific Desktop Features — JEP 272

Define a new public API to access platform-specific desktop features such as interacting with a task bar or dock, or listening for system or application events. API based on the Desktop object.

Not all platforms will support all features. The call Taskbar::isSupported allows to check which are available.

Some of the available features :

  • Login / Logout and screen lock handlers
  • Request user attention
  • Indicate task progress
  • Action shortcuts
  • etc …

Deserialization Filter — JEP 290

Allow incoming streams of object-serialization data to be filtered in order to improve both security and robustness. ObjectInputFilter that can be created :

interface ObjectInputFilter {
Status checkInput(Class<?> clazz,
long size, long nRefs, long depth, long streamBytes);
   enum Status { UNDECIDED, ALLOWED, REJECTED; }
}

XML Catalogs — JEP 268

Develop a standard XML Catalog API that supports the OASIS XML Catalogs standard, v1.1 :

https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html

The API will define catalog and catalog-resolver abstractions which can be used with the JAXP processors that accept resolvers.

Parser API for Nashorn — JEP 236

Define a supported API for Nashorn’s ECMAScript abstract syntax tree.

  • Provide interface classes to represent Nashorn syntax-tree nodes
  • Provide a factory to create a configured parser instance, with configuration done by passing Nashorn command-line options via an API
  • Provide a visitor-pattern API to visit AST nodes.
  • Provide sample/test programs to use the API.

Language Changes — JEP 213

Small language changes continue with Java 9 inside the JEP 213 : Milling Project Coin. At the program :

  • Private Interface Default Methods
  • Diamond Operator for Anonymous Classes
<T> Box<T> createBox(T content) {
// we have to put the `T` here
return new Box<T>(content) { };
}
  • Try-With-Resources on Effectively Final Variables
void doSomethingWith(Connection connection) throws Exception {
try(connection) {
connection.doSomething();
}
}
  • SafeVarargs on Private Methods
  • No More Deprecation Warnings for Imports

Extension to Existing APIs

A lot of existing APIs are a little bit refined. To name a few :

  • Optional, Stream, Collectors got a few new methods
  • New stream returning methods are added with LocalDate::datesUntil, Scanner::tokens, …
  • Many types of the DateTime API introduced in Java 8 can now transform themselves to epoch seconds, e.g. Chronology , LocalDate , and OffsetTime
  • etc …

Some Low Level APIs

Java 9 brings a number of very interesting APIs that operate much closer to the JVM. Amongst them :

  • Variable Handles aka VarHandles — JEP 193
  • Enhanced Method Handles — JEP 274
  • Dynamic Linking of Language-Defined Object Models — JEP 276
  • Spin-Wait Hints — JEP 285

Applet API deprecation — JEP 289

Deprecate the Applet API, which is rapidly becoming irrelevant as web-browser vendors remove support for Java browser plug-ins. Guide developers to alternative technologies such as Java Web Start or installable applications. Applet API is just marked as deprecated but not for removal. So, Applet API will still be in JDK 10 at least …

Excited about Java 9 ? Which feature is the most expected for you ? Tell us in comments !