Java 9 new features

Java 9 is scheduled to be released in July 2017.  The Feature Extension Complete milestone was achieved in late December,. We will have a look at the new features in Java 9.

Java 9 Features

Java 9 new Features

Java 9 new Features

  1. Module System (Jigsaw Project)
  2. JShell
  3. Collection Factory methods
  4. Private Methods in Interfaces
  5. Reactive Streams
  6. Multi Resolution Images API
  7. Process API
  8. Try-With Resources
  9. Diamond Operator Extension
  10. Deprated annotation Enhanced
  11. Unified JVM Logging
  12. SafeVarargs Scope Extension
  13. HTTP 2 Client
  14. HTML5 Javadoc
  15. Other changes

1. Module System  – Jigsaw Project

The major change in Java 9 is the module System that has already been implemented in Java 9.  The module system was introduced to make jdk scalable to smaller devices. The module system will provide application the capability to use only the jdk modules that are needed. The applications will no longer need the whole jdk framework. The module system will also encapsulate the public classes within a module. So a class defined public would not be available to the whole world until a module explicitly defines so. Because of this change the internal api e.g. com.sun.* of java will not be available anymore by default.

Let us now look at an example of a module in Java 9. Suppose we have a module com.programtalk.app and we would like to use java.logging module and com.programtalk.contract module in this module. We would have to define a file named as module-info.java and it has to  be placed in the top of java code hierarchy. And the module-info.java sample is as below:

module com.programtalk.app {
   requires com.programtalk.contract;
   requires java.logging;
}

In the below diagram, i will try to show a brief dependency model.

 

Java 9 module system

Java 9 module system

All the modules in the above diagram have the module-info.java file defining the dependencies and also defines what a module exports to the module that depends on it. All the packages that are not exported by module-info.java will not be available to dependent module.

To learn more about Module System you can read the Quick Start Guide

2. JShell – Java 9 interpreter

In Java, if we have to execute a simple statement, we do so by either creating a class with main method or creating a Test class that can be executed. This may not be that helpful when you are starting with Java and want to execute statements and see the results immediately.

JShell tries to solve this issue. JShell gives java developers the possibility to evaluate declarations, expressions , statements directly on the console without having to create classes.  JShell also has the possibility of loading the statements from  a file or to save the statements to a file. And JShell also has a very helpful autocomplete feature by using tab key. Here are some things to try with Jshell

|  Welcome to JShell -- Version 1.9.0-ea
|  Type /help for help

-> System.out.println("Hello JShell")
Hello JShell

Did you notice I didn’t write the semi-colon after the statement as it is not needed in JShell. Will save millions of keystrokes 🙂

3. Collection Factory methods

In Java 8 and before, it was possible to create an immutable view of the collections but only with some utility methods e.g. Collections.unmodifiableCollection(Collection<? extends T> c).  Let us create an immutable view of Collection in Java 8, with a one liner. This is the easiest way to do so in Java 8. It looks really bad and I even get a warning in eclipse about missing serialVersionUID.

Map<String, String> immutableMap = Collections.unmodifiableMap(
			   new HashMap<String, String>() {{
			     put("key1", "Value1");
			     put("key2", "Value2");
			     put("key3", "Value3");
			 }});
 As we have seen how hard it is to create an immutable view of Map in java 8 in a very simple manner, you would definitely agree with me that Java 9 has bought in something useful with the factory methods for creating immutable collections. Lets us now create the immutable Map in Java 9.
Map<String, String> immutableMap = Map.of("key1", "Value1", "key2", "Value2", "key3", "Value3");
Here are the examples of the factory methods
// empty immutable collections
List<String> emptyImmutableList = List.of();
Set<String> emptyImmutableSet = Set.of();
Map emptyImmutableMap = Map.of();

// immutable collections
List<String> immutableList = List.of("one", "two");
Set<String> immutableSet = Set.of("value1", "value2");
Map<String, String> immutableMap = Map.of("key1", "Value1", "key2", "Value2", "key3", "Value3");

4. Private Methods in Interfaces

Java 8 introduced default and static methods. Having private methods was first planned for Java 8 but got only implemented  in Java 9. Private methods in interfaces would allow the default and static method to share same code thus making code less redundant and more clean.  A private method can be either static so it belong to an interface. And a private method without static, and that can only be called on a instance of the interface but only within the interface.


public interface Java9InterfacePrivateMethod {
     
    private static String staticPrivateMethod2Share() {
        return "I belong to Interface";
    }
     
    private String privateMethod2ShareOnInstance() {
        return "I belong to instance";
    }
    
    default void callMyPrivateMethods() {
        // see the static method can be called right away just as any other static methods
        String result = staticPrivateMethod2Share();
   
        Java9InterfacePrivateMethod instance = new Java9InterfacePrivateMethod() {
            // nothing to implement
        };        
        System.out.println(instance.privateMethod2ShareOnInstance());
    }
}

5. Reactive Streams – Publish Subscribe Framework

Java 9 will also be come with Reactive Streams API. The class java.util.concurrent.Flow encloses the following 4 interfaces

These interfaces support the Reactive Streams publish-subscribe framework. Java 9 also provides a utility class SubmissionPublisher. A Publisher produces items that are consumed by a number of Subscribers. And a Subscriber is managed by a Subscription.  Subscription links the Publisher and Subscriber.

6. Multi Resolution Images API

Java 9 will support multi-resolution Image API in java.awt.image package. Interface java.awt.image.MultiResolutionImage would encapsulate images with different resolutions. And it provides two ways to access the images. Either get the list of all the resolution variants or get a particular variant based on the width and height.

Based upon the current display DPI metric and any applied transformations, the java.awt.Graphics class will retrieve the necessary variant from the MultiResolutionImage.
java.awt.image.AbstractMultiResolutionImage class provides the default implementation of java.awt.image.MultiResolutionImage.  The basic implementation of AbstractMultiResolutionImage  is java.awt.image.BaseMultiResolutionImage

7. Process API Improvements

Process API has been improved in Java 9 for controlling and managing operating-system process. With Java 9 it is possible to get information about any spawned process including the current process.

The  enhancements to java.lang.Process that have been added in Java 9 are

  • provide operating specific process id of a process
  • information about the process
  • the command of the the process
  • start time of the process
  • accumulated cpu time of the process
  • user name for the process

For getting the information about the process java.lang.ProcessHandle has been added in Java 9. ProcessHandle can be used to  destroy the processes.  You can also add an action to ProcessHandle.onExit() which will be executed when a process exists.

Here is an example that gets the information about the current process. I have executed it in jShell.


jshell> ProcessHandle currentProcess = ProcessHandle.current();
currentProcess ==> 12508

jshell>

jshell> System.out.println(currentProcess.getPid());
12508

jshell>

jshell> ProcessHandle.Info currentProcessInfo = currentProcess.info();
currentProcessInfo ==> [user: Optional[programtalk.com], cmd: C ... me: Optional[PT0.671875S]]

jshell>

jshell> Optional<String[]> args = currentProcessInfo.arguments();
args ==> Optional.empty

jshell> Optional<String> cmd = currentProcessInfo.commandLine();
cmd ==> Optional.empty

jshell>

8. Try-With Resources

In Java 7 try-with-resources was introduced but we always had to declare a variable in the try block that had to be managed by the try-with-resources statement.

void printFileJava7() throws IOException {
	    try(FileInputStream myInput = new FileInputStream("myfile.txt")) {
	        int data = myInput.read();
	        while(data != -1){
	            System.out.print((char) data);
	            data = myInput.read();
	        }
	    }
	}

Java 9 has relaxed this requirement and has allowed to declare a variable outside the try-with-resources statement but the only condition is that the variable has to be final or effectively final.

void printFileJava9() throws IOException {
		final FileInputStream myInput = new FileInputStream("myfile.txt")
	    try(myInput) {
	        int data = myInput.read();
	        while(data != -1){
	            System.out.print((char) data);
	            data = myInput.read();
	        }
	    }
	}

 

9. Diamond Operator Scope Extension

Java 7 gave us diamond operator to make our lives bit easier.In the below example you can see that java 7 list is more readable and concise.


List<String> preJava7 = new ArrayList<String>();
List<String> java7 = new ArrayList<>();

But Java 7 diamond operator was not allowed on anonymous classes.  But Java 9 has enhanced the Diamond operator to work even on anonymous classes. The below example will only compile in Java 9


 List<String> list = new ArrayList<>(){ };

10. Deprecated annotation Enhanced

 @Deprecated annotation is used to mark a Java API. It can have lots of meanings like an API will be removed in near future and no body knows when. It can also mean that this API is broken and should no longer be used. It can mean a lot of things. So as to provide more information with @Deprecated annotation, forRemoval and since have been added.
 And Java SE 9 also provdes a tool jdeprscan that scans a jar file. This tool scans a aggregation of class for uses of deprecated API elements from Java SE. This tool will be useful for application that use libraries that have already been compiled and the user of that library has no idea as to what deprecated APIs it is using.

11. Unified JVM Logging

Unified JVM Logging tries to introduce a common easy-to-configure logging for all components of the JVM.  With earlier Java versions it is hard to configure logging for various JVM components. e.g. If you want to log a message per GC you need to configure -XX:+PrintGC  on the jvm start. And there are lots of other components that provide there own configurations for logging out messages. And often these messages would end of in different file rather than the logging file of the application.

Java 9 has shown a good intent in having minimal configurations needed and following the already existing logging message styles to log the JVM component logs. A set of tags has been defined by the logging framework in the JVM e.g. gc, threads, compiler etc. Each message logged has to have a one or more tags associated so that the logging compoenent is clear.  A log message also has a level e.g; error, info, debug, trace. A message can also be decorated with other information like time, uptime etc.

A new command-line option has been added -Xlog which has options to be defined like the tagset, decorators, logging level etc.

-Xlog:gc=trace:file=gctrace.txt:uptimemillis,pids:filecount=5,filesize=1024
    - log messages tagged with 'gc' tag using 'trace' level to
    a rotating fileset with 5 files with size 1MB with base name
    'gctrace.txt' and use decorations 'uptimemillis' and 'pid'
    - default output of all messages at level 'warning' to 'stderr'
    will still be in effect
 One very nice feature that has also been taken care of the changes to the logging configuration at runtime. Logging can be controlled at runtime through Diagnostic Commands (the jcmd utility). It allows all the options that are available at runtime.  jmcd usage
Usage: jcmd <pid | main class> <command ...|PerfCounter.print|-f file>
or: jcmd -l
or: jcmd -h

command must be a valid jcmd command for the selected jvm.
Use the command "help" to see which commands are available.
If the pid is 0, commands will be sent to all Java processes.
The main class argument will be used to match (either partially
or fully) the class used to start Java.
If no options are given, lists Java processes (same as -l).

PerfCounter.print display the counters exposed by this process
-f read and execute commands from the file
-l list JVM processes on the local machine
-h this help
Read more JEP158

12. SafeVarargs Scope Extension

   Until Java 8, @SafeVarargs could only be applied to static methods, final methods and constructors.  None of them can be overridden. This list was missing one more candidate that could also not be overridden and that was a private method.  And Java 9 has made it possible to add @SafeVarargs to the private method. Here is a valid example in Java 9 but in Java 8 it throws compile error “@SafeVarargs annotation cannot be applied to non-final instance method iAmSafeVaragrsMethod
	@SafeVarargs
	private void iAmSafeVaragrsMethod(String... varagrgs)
	{
	   for (String each: varagrgs) {
	      System.out.println(each);
	   }
	}

13. HTTP 2 Client

Java 9 comes with a new HTTP client API which supports HTTP/2 and websockets.  This would replace the legacy HTTPURLConnection API. This change couldn’t be finished in Java 9. It is available in the incubator module.  So this module will not available on the classpath by default and would have to added to the classpath by configuring it using --add-modules command-line option.

Let’s create a HTTPRequest  and get the response asynchronously.


	URI testPageURI = new URI("http://127.0.0.1:8080/testPage");
	CompletableFuture<HttpResponse> nonBlockingResponse =  HttpRequest
	        .create(testPageURI)
	        .GET().responseAsync();
	int tries = 0;
	while(!nonBlockingResponse.isDone() && tries++ < 5) { Thread.sleep(5); } if (nonBlockingResponse.isDone()) { HttpResponse response = nonBlockingResponse.get(); System.out.println("status code : " + response.statusCode() + " --> " +  response.body(HttpResponse.asString()));
	}
	else {
		nonBlockingResponse.cancel(true);
	    System.out.println("Cancelling, could not get response");
	}

 

14. HTML5 Javadoc

Java 8 and below generate the javadocs  in HTML 4 which is quite old. In Java 9 a command line option is added to javadoc utility to request a HTML 4 or HTML 5 output. HTML 4 will be the default for now but in later jdk releases HTML5 would become the default. The three-frame structure of the javadocs has not changed and will keep to remain the same with HTML 5 javadocs.

15.  More features

  • underscore character is reserved. A variable can no longer be named only _
  • Applet API is deprecated
  • javac will drop support for Java 1.4 and older source code.
  • Java browser plugin is deprecated in Java 9
  • Stack-Walking API – API for stack walking that allows easy filtering of, and lazy access to, the information in stack traces.
  • Experimental support for cgroup memory limits in container (ie Docker) environments(See here)
  • Search box in java docs (JEP 225)- modules, packages, types and members are searchable now in javadocs.  A very nice feature that will definitely be helpful for the developers.

Feature that couldn’t make to Java 9

Summary

I have tried to give an overview of the major Java 9 features. And would be updating the links to the detailed articles. I would be writing about these features in details.  Java 9 seems to be an exciting change for the JVM framework itself as it will be a modular system.

 

Like this post? Don’t forget to share it!