Preparing for Java 9. Review of the most interesting improvements

On this Wednesday, August 30, at the office of Oracle, meeting JUG with Oleg Shelaev, Developer Advocate in the company ZeroTurnaround, which makes JRebel and XRebel. The topic of the meeting is the tools for creating multi-threaded Java programs (from designing bikes and starting threads to handles, to ForkJoinPools, green threads and transactional memory).
Of course, we asked which Java 9 chips are considered the most useful in ZeroTurnaround. As a result, they got hold of the article that you are reading right now. The original article Oleg published in the blog RebelLabs , there are many more interesting.
So, have begun.
We've been waiting for Java 9 for a long time, and now, the release is just around the corner. Hooray! This was not the easiest way, but nevertheless, even the hottest disputes about the system of modules are gradually moving forward, and most of the participants agree. Most likely, the release will take place very soon, for example, on September 21, 2017.
In this post, I will not dwell on a detailed discussion of the system of modules. Instead, we'll talk about things that any developer can use: innovations in the Java language and standard APIs.
Next is a list of our favorite innovations in the Java 9 API. In principle, to understand the essence, it is enough to look at the code examples. But you can run JShell and yourself all these examples, with your own eyes to look at the results.
Run JShell, I'll wait ... ready? Not yet? Okay ... did you? Still no? Yes, it takes time to burn up ... ok, it's started, great! Begin.
Factory methods for collections
One of the most anticipated chips in Java 9 is the ability to make literals of collections to make it easier to write down the simplest cases. Joke, of course , we're talking about Java, we do not have literals, there are only static factory methods. However, now we can easily create a List, Map and Set using the ready methods:
jshell> List.of(1, 2, 3)
$1 ==> [1, 2, 3]

jshell> Set.of(1, 2)
$2 ==> [2, 1]

jshell> Map.of("hello", "world")
$3 ==> {hello=world}
This is made possible by the appearance of static methods in interfaces (Java 8), which are used by Lear, Map and Set.
As a result, a non-commercially available collection is created, optimized for maximum performance. For example, List1 stores a value in the class field, which speeds up access to it.
jshell> List.of(1).getClass()
$4 ==> class java.util.ImmutableCollections$List1
In Stream API added a couple of very useful features. In particular, the methods droWhile and takeWhile. As you can guess by name, dropWhile throws the elements from the beginning and until the condition is met, and ifWake - takes the elements until the condition is met.
jshell> IntStream.range(1, 10).dropWhile(x -> x < 5).forEach(System.out::println)
The next useful addition is the methoditerate (). It allows you to replace the cycles with streams. You need to give him the initial value of the stream, the condition (when you need to stop the iterations), and the transition function (how exactly will the next element be obtained).
jshell> IntStream.iterate(0, x -> x < 3, x -> x + 1).forEach(System.out::println)
If you suddenly want to do fixed-point calculations on streams, this dream can be fulfilled in Java 9.
If suddenly someone does not remember how to use them, we have a excellent crib . In Java 9, finally added a methodor (), which allows you to bind different Optionals in one line, without going down to constant checks onisPresent ().
public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)

jshell> Optional.empty().or(() -> Optional.of("RebelLabs"))
$5 ==> Optional[RebelLabs]
The next good addition is the ability to convert Optional to a stream containing no more than one element. This is really useful if you want to use lazy streams. In the example below, you can see the difference with your own eyes. If you call map () on Optional, the mapping will occur instantly, but on the stream - no.
jshell> Optional.of(1).map(x -> x * 3)
$10 ==> Optional[3]

jshell> Optional.of(1).stream().map(x -> x * 3)
$11 ==> [email protected]
Finally, we have the methodPresentOrElse. In Java 8, you could define a behavior only for the case where the Optional value exists. In Java 9, it became possible to specify two different Runnable, specifying what to do if the value exists, and if it does not exist.
jshell> Optional.empty().ifPresentOrElse(x -> System.out.println(x), () -> System.out.println("empty"));
Completable future
Another piece of the API, which was thoroughly polished, was theCompletableFuture class. It added a couple of great things, allowing you to write even more correct multi-threaded code.
One of the coolest methods iscopy (), which returns a non-cost copy of this CompleteFuture. In the following example, we create a CompleteFuture, make a copy of it, and verify that the completion of the copy does not affect the original object. This is very, very useful when creating an asynchronous API that returns a CompleteFuture. Previously, it was necessary to suffer badly, revising the situation when the client can complete the completeFuture returned from such API himself. Now it's enough just to call the methodcopy ().
jshell> CompletableFuture<String> future = new CompletableFuture<>()
future ==> [email protected][Not completed]

jshell> future.copy()
$15 ==> [email protected][Not completed]

jshell> future.isDone()
$17 ==> false

jshell> $15.isDone()
$18 ==> false

jshell> $15.complete("JRebel")
$19 ==> true

jshell> $15.isDone()
$20 ==> true

jshell> future.isDone()
$21 ==> false
But the coolest thing is that the parent stoppage applies to all copies!
jshell> CompletableFuture<String> future = new CompletableFuture<>()
future ==> [email protected][Not completed]

jshell> future.copy()
$24 ==> [email protected][Not completed]

jshell> future.complete("XRebel")
$25 ==> true

jshell> $24.isDone()
$26 ==> true
In addition, at last timeouts were added in them. Working with the asynchronous API, without the built-in functions for working with timeouts, was very stressful. In Java 9, it became possible to specify exactly how to complete the CompleteFuture, after a manually expired timeout.
jshell> CompletableFuture<String> future = new CompletableFuture<>()
future ==> [email protected][Not completed]

jshell> future.completeOnTimeout("Isn't this amazing", 1, TimeUnit.SECONDS)
$28 ==> [email protected][Not completed, 1 dependents]

jshell> future.isDone()
$29 ==> true
Process Control API
Prior to Java 9, process management was not done as cross-platform as one would like to believe. Work with subprocesses used to be somewhat curve, and in Java 9 it was finally straightened out. Java 9 adds the ProcessHandle class, which provides an API for analyzing the current process, other processes found by the pid, their child processes, and so on. Just look at the example:
jshell> ProcessHandle current = ProcessHandle.current();
current ==> 6349

$33 ==> 6349

arguments() command() commandLine() equals( getClass()
hashCode() notify() notifyAll() startInstant() toString()
totalCpuDuration() user() wait(

$34 ==> Optional[/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/bin/java]
Most likely, the most commonly used function will be getting the command line and arguments used to start the process, but the rest of the features are also quite worthy of attention.
Another popular task that will be much more convenient to do in Java 9 is to run the code right after the process is completed. Java 9 offers a new method for this:
CompletableFuture<Process> onExit() Specify what you want to do, and it just works. There are no more tears and unstable foreign libraries.
Rejoice, haters of exceptions! Now you can work with Streckrays without creating Exception objects. Welcome to StackWalker!
StackWalker gives you the ability to wander around the stack, filter it, and effectively do various other things. This example will pull out the top 5 elements from the stacks:
jshell> StackWalker.getInstance().walk(s -> s.limit(5).collect(Collectors.toList()));
$36 ==> [do_it$(java:36), jdk.jshell/jdk.jshell.execution.DirectExecutionControl.invoke(, jdk.jshell/jdk.jshell.execution.RemoteExecutionControl.invoke(, jdk.jshell/jdk.jshell.execution.DirectExecutionControl.invoke(, jdk.jshell/jdk.jshell.execution.ExecutionControlForwarder.processCommand(]
Improvements in Java
Improved not only API, but the language itself. First, the symbol_ (underscore) is no longer a valid identifier. If you use it for some reason, you will have to switch to double underscore! (Hint: do not do this).
jshell> int _ = 1
| Error:
| as of release 9, '_' is a keyword, and may not be used as an identifier
| int _ = 1
| ^
| Error:
| reached end of file while parsing
| int _ = 1
| ^

jshell> int __ = 1;
__ ==> 1
This is so that in the future it is possible to replace unnecessary (optional) parameters with the function call.
Interfaces, too, slightly modified. Interfaces in Java 9 can contain private methods. In Java 8, we were able to store some common logic in default methods. Now we can allocate common logic inside the interfaces, without the need to create auxiliary classes.
Here's a small synthetic example:
jshell> interface A { private int zero() { return 0;} default int one() { return zero() + 1;}}
| created interface A
And finally, the last innovation. Now you can use effectively final variables in try-with-resources blocks. This simplifies the code, you do not need to declare the variables inside the text anymore. Just work with them in the block, and it's compiled.
boolean a() throws Exception {
Socket s = new Socket();
try (s) { }
return s.isClosed();
After the block is executed, all the AutoClosable mentioned there will naturally close.
Hooray! We've looked at a lot of things, and not all of the innovations that appeared in Java 9. However, the things listed above seem most useful to us, and will be used as soon as possible.
The release of Java 9 has been preparing for quite some time, and it's time for us all to figure out how it will affect us. Now it's more relevant than ever, considering that the mode of working with clasthpath will remain unchanged, and the transition to Java 9 can be simple and painless. You can right away download the finished assembly of Java 9 , deal with the new APIs, try them out, and prepare for the upcoming bright future!
Oleg Shelayev is a Java developer and Developer Advocate in ZeroTurnaround. When I do not write java agents or tests, I write to the RebelLabs blog or speak at conferences. In his spare time he tries to promote science at the University of Tartu, studying the problems of dynamic software updates.
Papay 14 october 2017, 11:49
Vote for this post
Bring it to the Main Page


Leave a Reply

Avaible tags
  • <b>...</b>highlighting important text on the page in bold
  • <i>..</i>highlighting important text on the page in italic
  • <u>...</u>allocated with tag <u> text shownas underlined
  • <s>...</s>allocated with tag <s> text shown as strikethrough
  • <sup>...</sup>, <sub>...</sub>text in the tag <sup> appears as a superscript, <sub> - subscript
  • <blockquote>...</blockquote>For  highlight citation, use the tag <blockquote>
  • <code lang="lang">...</code>highlighting the program code (supported by bash, cpp, cs, css, xml, html, java, javascript, lisp, lua, php, perl, python, ruby, sql, scala, text)
  • <a href="http://...">...</a>link, specify the desired Internet address in the href attribute
  • <img src="http://..." alt="text" />specify the full path of image in the src attribute