Java

Java 9 features

Java 8 release represented a new stepping stone in the history of java. It marks the transition to functional style programming. Most of us are working with 8, but let’s see what it was introduced in 9. It is a minor release, but we must understand where java is going because of the 6 month releases and changes are going to be incremental. With these incremental changes there is a chance to test out some functionalities to see how developers react to them, to see how they play out. All the non-LTS releases represent a sandbox if you want. Let’s check out some the relevant features that were introduced in java 9.

Collection factory methods

If you read Joshua’s block Effective Java 3rd Edition, you already are familiar with constructor factory methods. These are just an extension of that.

List<String> list = List.of("a", "b", "c");
Map<String, Integer> immutableMap = Map.of("one",1, "two", 2);

Stream API improvements

These are straightforward. There are four new methods added to the Stream interface: iterate,dropWhile, takeWhile, ofNullable. The iterate method gets a new overload, allowing you to provide a Predicate on when to stop iterating:

IntStream.iterate(1, i -> i < 10, i -> i + 1).forEach(System.out::println);
//drop while examples and others !!!!!!!!!!

The takewhile() will discard the stream after the element that does not match the condition

Stream.of(2, 4, 5, 7, 8)
    .takeWhile(i -> i % 2 == 0)
    .forEach(System.out::println); 
//prints 2,4

The dropwhile() will discard the elements before the element that does not match the condition including all the elements after

Stream.of(2, 4, 5, 7, 8)
    .dropWhile(i -> i % 2 == 0)
    .forEach(System.out::println); 
//prints 5,7,8

ofNullable() represents the null check for the stream. The following code will print 0

System.out.println(Stream.ofNullable(null).count());
//prints 0

Http/2 client

This is something that is useful. The old style was too verbose and this is a breath of fresh air. Sure if you are working with spring it would be something that you will still ignore as the RestTemplate is more mature.

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
     .uri(URI.create("http://service")).GET()
     .build();
        
HttpResponse<String> response =client.send(request,BodyHandlers.ofString());
System.out.println(response.statusCode());

Private interface methods

When default methods were introduced in 8 I had the feeling that they broke the beauty of interfaces. Suddenly they weren’t contracts anymore. Since then I accepted them in some way, especially in the context of spring data. Now java 9 brings private interfaces. Seems that feeling is coming back to me. Anyways, you can now write:

public default void method1() {
    method2(); 
}
     
private void method2(){
    System.out.println("private method");
}

Diamond Operator Extension

You can now use the diamond operator <> in anonymous classes.

Predicate<Integer> isFortyTwoTheAnswer = new Predicate<>() {
    @Override
    public boolean test(Integer input) {
        return input == 42;
    }
};

But now we have lambdas so this can be rewritten

Predicate<Integer> isFortyTwoTheAnswer = input -> input == 42;

Try-With-Resources Enhancements

It adds extra enhancements to the java 7 try with resources so now we can write

private static void print() throws IOException {
    FileInputStream input = new FileInputStream("source.txt");
    try(input) {
        int data = input.read();
        while(data != -1){
            System.out.print((char) data);
            data = input.read();
        }
    }
}

Optional Class Improvements

These are self describing. The most noticeable change is the stream() method.

Optional.ofNullable(null)
.ifPresentOrElse(System.out::println, () -> System.out.println("null"))

Optional.of("something").or(() -> Optional.of("empty"))

Optional.empty().stream().forEach(System.out::println)

CompletableFuture API Improvements

Here we have support for delays and timeouts. Simple and straightforward.

public CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)

public CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)

It was also added new factory methods.

public static <U> CompletableFuture<U> completedFuture(U value)

public static <U> CompletionStage<U> completedStage(U value)

public static <U> CompletionStage<U> failedStage(Throwable ex)

G1 – default garbage collector

Compared to most other garbage collectors, the G1 has two big advantages: it can do most of its work concurrently and it uses non-continuous spaces, which enables it to efficiently deal with very large heaps. Like other collectors which split the memory into eden, survivor and tenured G1 splits the heap into many small regions. It selects the zones with the most garbage. One difference from old GCs is the fact is does not have to run through the entire heap, thus making it much faster. And it can collect new and old generation in the same time. It has four phases: initial mark(suspending), concurrent mark, final mark(suspending) which is actual cleanup and evacuation phase.

Module System

This is similar to OSGI, where you work with bundles and you export only certain features in the manifest. To be honest OSGI has not gained that many traction, so this is a surprise for me. Like OSGI is focused on deep encapsulation and high cohesion. Not something I am very enthusiast about but let’s see what the future holds for this. More details here.

JDK changes

With the addition of the module system it was necessary to change the structure of the JDK to support this. This is the JDK 8.

Starting with 9 it has changed to

This is hotspot, OpenJdk is slightly different

The bin directory now contains the executable and command-line launchers that are defined by the modules linked to the image.

The conf directory contains the properties, policies and other configuration files intended for developers.

The include directory contains C-language header files that support native-code programming with JNI and JVM Debugger Interface.

The jmods directory contains the compiled module definitions.

The legal directory contains copyright and license files for each module.

Lib directory is the old JRE.

JDeps

This a part of the bin directory. It’s a new tool that allows us to analyse the statically declared dependencies between classes.

jdeps -include com.sergiuoltean.service. *-e com.sergiuoltean.service.*  -R -filter:package .

JShell

This is also known as REPL(Read-Eval-Print-Loop). It’s purpose it to try the out the features in a fast way. Probably this will be used by newbies, but it is not something I would recommend for my trainees. Most of the time a dive into the code it’s more efficient.

JLink

Let’s say some of the JDK modules are not required. In that case why bring them into your deployable? You can create a minimum amount of dependencies, which the dockerized environments will love.

Multi-release JARs

Backward compatible is the keyword here. This allows you to put the same functionality for multiple versions. For example if there is a class that is not forward compatible with the new java version(should not be the case), you can just keep the class as is in the same jar, and refactor/redo the new version of the class compatible with the new java version. Its use cases are pretty narrow, so I won’t invest too much into this.

Reactive Streams Support

Starting with 9 it was added reactive support. Reactive programming refers to managing resources as effectively as possible, to get out the most of the system that we have. It’s very effective especially in the cloud where every cent counts. But since memory it’s cheap it hasn’t yet get the traction I expected. Will see what the future holds. Anyways the reactive support consists of four concepts introduced:

public interface Publisher<T> {
    void subscribe(Subscriber<? super T> s);
}

public interface Subscriber<T> {
    void onSubscribe(Subscription s);
    void onNext(T t);
    void onError(Throwable t);
    void onComplete();
}

public interface Subscription {
    void request(long n);
    void cancel();
}

public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {}

Container Updates

Previous to 9(and 8u131), when setting the memory limits was troublesome when working with docker. Basically it always used the native memory and ignoring docker. More on this here. With this release java added support for containers. The JVM will now consider cgroups memory limits if the following flags are specified:

-XX:+UseCGroupMemoryLimitForHeap
-XX:+UnlockExperimentalVMOption

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.