Java 11 is here to stay!

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:

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.

One thought on "Java 11 is here to stay!"

  1. Michael says:

    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?

Leave a Reply

Your email address will not be published. Required fields are marked *