Wrapping up Java 9 new Features

Java 9 comes with a rich feature set. Although there are no new language concepts, new APIs and diagnostic commands will definitely be interesting to developers.

In this write up we’re going to have quick, high level look at some of the new features;

Modular System – Jigsaw Project

Modularity is a general concept. In software, it applies to writing and implementing a program or computing system as a number of unique modules, rather than as a single, monolithic design.

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.

Simply put, the modules are going to be described in a file called module-info.java located in the top of java code hierarchy:

module me.aboullaite.java9.modules.car {
   requires me.aboullaite.java9.modules.engines;
   exports me.aboullaite.java9.modules.car.handling;
}

Our module car requires module engine to run and exports a package for handling.

For more in-depth example check OpenJDK Project Jigsaw: Module System Quick-Start Guide.

JShell - Java 9 REPL

"What is an REPL?" you ask. An REPL is a command-line tool for quickly running statements.

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.

Collection Factory methods

Before Java 9, 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). For example, 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 bad! isn't ?

Map<String, String> immutableMap = 
Collections.unmodifiableMap(
           new HashMap<String, String>() {{
             put("key1", "Value1");
             put("key2", "Value2");
             put("key3", "Value3");
         }});

Java 9 brings Now, 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");

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.

    interface InterfaceWithPrivateMethods {

        private static String staticPrivate() {
            return "static private";
        }

        private String instancePrivate() {
            return "instance private";
        }

        default void check() {
            String result = staticPrivate();
            InterfaceWithPrivateMethods pvt = new InterfaceWithPrivateMethods() {
                // anonymous class
            };
            result = pvt.instancePrivate();
        }
    }}

Reactive Streams

The Flow APIs in JDK 9 correspond to the Reactive Streams Specification, which is a defacto standard. JEP 266 contains a minimal set of interfaces that capture the heart of asynchronous publication and subscription. The hope is that in the future 3rd parties will implement them and thus convene on a shared set of types.

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.

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.

The new API which is defined in the java.awt.image package can help us:

  • Encapsulate many images with different resolutions into an image as its variants.
  • Get all variants in the image.
  • Get a resolution-specific image variant – the best variant to represent the logical image at the indicated size based on a given DPI metric.

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.

Process API Improvements

So far there has been a limited ability for controlling and managing operating system processes with Java. For example, in order to do something as simple as get your process PID today, you would need to either access native code or use some sort of a workaround. More than that, it would require a different implementation for each platform to guarantee you’re getting the right result.

In Java 9, expect the code for retrieving Linux PIDs, that now looks like this:

    public static void main(String[] args) throws Exception
    {
    Process proc = Runtime.getRuntime().exec(new String[]{ "/bin/sh", "-c", "echo $PPID" });

    if (proc.waitFor() == 0)
    {
    InputStream in = proc.getInputStream();
    int available = in.available();
    byte[] outputBytes = new byte[available];

    in.read(outputBytes);
    String pid = new String(outputBytes);

    System.out.println("Your pid is " + pid);
    }
    }

To turn into something like this (that also supports all operating systems):

System.out.println("Your pid is " + Process.getCurrentPid());

The update will extend Java’s ability to to interact with the operating system: New direct methods to handle PIDs, process names and states, and ability to enumerate JVMs and processes and more.

Try-With Resources

In Java 7, the try-with-resources syntax requires a fresh variable to be declared for each resource being managed by the statement.

In Java 9 there is an additional refinement: if the resource is referenced by a final or effectively final variable, a try-with-resources statement can manage a resource without a new variable being declared:

  MyAutoCloseable mac = new MyAutoCloseable();
  try (mac) {
      // do some stuff with mac
  }

  try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
     // do some stuff with finalCloseable
  } catch (Exception ex) { }

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<>(){ };

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 nobody 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 provides 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.

Unified JVM Logging

Today it’s hard to make sense of the root cause for performance issues and crashes of the JVM. One way to tackle this is introducing one single system for all JVM components that would allow fine-grained, and easy-to-configure JVM logging. Currently, different components of the JVM use different mechanisms and conventions for logging, making it harder to debug.

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);
         }
      }

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");
      }

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.

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.

Ressources:
+ http://openjdk.java.net/projects/jdk9/