Java 11 has been released! Let us get you up to speed on the highlights of this release.
Java 11 is the first LTS (Long Term Support) release since Java 8. This is important because any software built upon it will have commercial support until at least 2023.
So, how does this work for Java 9 and 10, one might wonder? Guess what: commercial support, even extended, for these versions is already finished.
Meaning, you can bet that Java 11 is the next ‘big’ release since Java 8, at least as far as support goes. And middleware like application servers will also most likely choose Java 11 as their next big iteration.
The image below shows when different kinds of support will end for each Java version. As you can see, commercial support for Java 9 and 10 has effectively ended already, while Java 8 and Java 11 continue to enjoy commercial support until at least 2022 and 2023, respectively.
A word of caution
Apart from taking commerical support into consideration, the licence agreement of the commercial Oracle JDK has changed. It is no longer free for production use. If you want to use and deploy Java 11 free of charge, you should use the OpenJDK build, also from Oracle. You can get it here: http://jdk.java.net/11/
Java 9 and 10 recap
Before Java 11, Java 9 and 10 introduced a lot of new stuff. A few highlights are:
- The module system (project Jigsaw). By introducing encapsulation at the module level, it becomes easier for developers to shield implementation details from potiential consumers. An excellent primer can be found here: https://www.baeldung.com/java-9-modularity
- JShell, a REPL environment for Java. This allows developers to quickly try out java code without needing to compile and run a class. The reference is here: https://docs.oracle.com/javase/10/jshell/introduction-jshell.htm
- Local variable type inference. No need to explicitly declare the type of local variables, in most cases the type can be inferred. See our previous blog on Java 10 at https://craftsmen.nl/java-10-in-5-minutes/ for an explanation on how this works.
On to Java 11
So what does Java 11 add to this? Well, apart from a lot of under-the-hood stuff like adding of new crypto algorithms and JVM optimalisations (JEPs listed at http://openjdk.java.net/projects/jdk/11/), let’s discuss new stuff in Java 11 that will appeal to most developers:
- Explanation of new language features
- HttpClient and Websocket Client
- Other API changes
- Flight Recorder tool
- The ability to launch single source file programs
Where to get it?
As previously stated, you can download the Oracle OpenJDK 11 at http://jdk.java.net/11/
Language changes
Java 11 adds local variable syntax for lamba parameters. Although it is not a big change, it is more concise to what you would expect from local variable type inference.
As an example, given that ITest is a functional interface taking two Integer objects and emitting a result, you can specify the parameter types in the function declaration.
ITest test = ( Integer x, Integer y) -> x + y;
In Java 11, you can now use var parameters:
ITest test = ( var x, var y) -> x + y;
It’s no big change, but you can now omit the type while still adding annotations:
ITest test = ( @NotNull var x, @NotNull var y) -> x + y;
HTTP Client and WebSocket Client
At last, Java 11 has a standardized HTTP client capable of WebSocket connections! The client was already prototyped since Java 9, but Java 11 on, the API is standardized. You can find the http client in the Java package java.net.http.
A quick example of the HTTP client doing a GET request on a local URL:
HttpClient client = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_1_1) .followRedirects(HttpClient.Redirect.NORMAL) .connectTimeout(Duration.ofSeconds(20)) .build(); HttpRequest httpRequest = HttpRequest .newBuilder() .header("myHeader", "myValue") .uri(URI.create("http://localhost:4567/hello")) .build(); HttpResponse<String> response = client .send(httpRequest, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); System.out.println(response.body());
See, it has a nice fluent API, much easier than the previous, which used HttpUrlConnection. There’s also support for asynchronous requests.
WebSocket client
In order to build a WebSocket client, you have to implement the WebSocket.Listener interface first. Here’s an example. As you see, you can override several callback methods that you can give the desired behaviour.
public class WebSocketClient implements WebSocket.Listener { @Override public void onOpen(WebSocket webSocket) { ... } @Override public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) { ... } @Override public CompletionStage<?> onBinary(WebSocket webSocket, ByteBuffer data, boolean last) { ... } @Override public CompletionStage<?> onPing(WebSocket webSocket, ByteBuffer message) { ... } @Override public CompletionStage<?> onPong(WebSocket webSocket, ByteBuffer message) { ... } @Override public CompletionStage<?> onClose(WebSocket webSocket, int statusCode, String reason) { ... } @Override public void onError(WebSocket webSocket, Throwable error) { ... } }
Now, you can use the HttpClient to instantiate a WebSocket connection, in this example to a local server:
CompletableFuture<WebSocket> server_cf = HttpClient. newHttpClient(). newWebSocketBuilder(). buildAsync(URI.create("ws://localhost:4567/echo"), new WebSocketClient()); WebSocket server = server_cf.join(); server.sendText("Hello!", true);
Other API changes
Java 11 adds a few nice API changes that make a developer’s life a little easier.
String class
A few nice methods for stripping, repeating and parsing text have been added.
// strips whitespaces " \0019hi ".strip() -> "\u0019hi" " \0019hi ".stripLeading() -> "\u0019hi " " \0019hi ".stripTrailing() -> " \u0019hi" //checks if a string is empty or contains only whitespaces " ".isBlank() -> true //repeats string n times "ha".repeat(10) -> "hahahahahahahahahaha" // splits string into lines, yielding a stream of strings "line1\r\nline2\rline3\nline4" .lines() .stream() .forEach(System.out::println) -> line1 line2 line3 line4
ByteArrayOutputStream class
Up until now, there was no method to directly write all bytes from a source into a ByteArrayOutputStream. Now there is. Convenient!
//java 10 byteArrayOutputStream.write(myString,getBytes(), 0, myString.length()) //java 11 byteArrayOutputStream.writeBytes(myString,getBytes())
Optional class
An isEmpty() method has been added, no more need for !isPresent(). How did we ever use Optional without it?
if (optional.isEmpty()) {...}
More API changes can be found in the demo. A download link is at the end of this article.
Flight recorder
This profiling and monitoring tool, previously a commercial addition to the JVM, is now an integral, open-sourced, part of Java 11. For the JVM to emit information about its inner workings, just add the StartFlightRecording parameter to your startup command.
As an example, we add the default Flight Recorder behaviour here, which is just emitting data when asked by a client.
java -XX:StartFlightRecording=settings=default nl.craftsmen.java11demo.MyClass
For more options, see the Flight Recorder reference here: https://docs.oracle.com/javacomponents/jmc-5-4/jfr-runtime-guide/about.htm
Consuming flight recorder data
You can process the data with Java Mission Control (JMC), an application that consumes all Flight Recorder data. Up until *and including* Java 10, JMC was part of the JDK. From Java 11 on, it’s not. JMC is now open source, and downloadable as a separate product at http://jdk.java.net/jmc/.
Below is a screenshot of what JMC looks like when running.
Launch single-file source programs
For educational purposes and quick turnarounds (but JShell is even faster), you are able to run Java programs now that consist of one file, without needing to explicitly compile.
For example, consider a Java class called MultiplierProgram with a main method that takes one argument and prints its squared value:
public class MultiplierProgram { public static void main(String[] args) { Multiplier multiplier = new Multiplier(); System.out.println(args[0] + " multiplied by itself yields " + multiplier.multiply(Integer.valueOf(args[0]))); } static class Multiplier { int multiply(int x) { return x * x; } } }
From Java 11 on, you can run this program directly without needing to compile it.
java Multiplier.java 2 => 2 multiplied by itself yields 4
A limitation is that the program must be a single-source file. However, nothing keeps you from declaring multiple inner classes, as the example shows.
Summary
Java 11 is the first LTS release of the Java platform that combines all the added functionality of Java 9, 10 (and 11, of course!).
It’s a big step forward again compared to Java 8 (which was the first LTS release) and ensures the continuing innovation of the Java platform.
All in all, it is fair to say, it looks like Java 11 is here to stay.
- You can download JDK 11 at http://jdk.java.net/11/
- A demo of the new language and API capabilities of Java 11 is located at https://github.com/MichelSchudel/java11demo
Hi, This has been very useful for building out a WebSocket client. I have run into one problem that I have not been able to solve. I have a text message that is more than 4K bytes and this seems to cause some kind of fragmentation and corrupts the message for the server. I have tried to split the message manually but I end up with the same result. Is there something special required to send text messages larger than 4k?