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
- Module System (Jigsaw Project)
- JShell
- Collection Factory methods
- Private Methods in Interfaces
- Reactive Streams
- Multi Resolution Images API
- Process API
- Try-With Resources
- Diamond Operator Extension
- Deprated annotation Enhanced
- Unified JVM Logging
- SafeVarargs Scope Extension
- HTTP 2 Client
- HTML5 Javadoc
- 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.
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"); }});
Map<String, String> immutableMap = Map.of("key1", "Value1", "key2", "Value2", "key3", "Value3");
// 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.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
jcmd
utility). It allows all the options that are available at runtime. jmcd
usageUsage: 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
12. SafeVarargs Scope Extension
@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
- JSON API
- Local-Variable Type Inference (var) is most probably going to Java 10
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.
I am very excited about the modular system as we ship the jdk along with the our webservice client. Now we can only ship some of the components for the jdk. I love jdk9.
Almost all of the features are not so important in my opinion. Java 9 is not so interesting and will have very few users switching to Java9.
If you are too excited about the Project Jigsaw, please go through this post https://developer.jboss.org/blogs/scott.stark/2017/04/14/critical-deficiencies-in-jigsawjsr-376-java-platform-module-system-ec-member-concerns?_sscc=t
Before you start to raise red flags, read this article also https://blog.plan99.net/is-jigsaw-good-or-is-it-wack-ec634d36dd6f
Private methods in interfaces? First default methods and now private methods, I don’t know what is coming next in interfaces.
Thanks for sharing. Just to add some info that IBM and Red Hat to Vote “No” on Java Modules (Jigsaw) https://www.infoq.com/news/2017/05/no-jigsaw
Thanks, nice post