Author: I don’t have three hearts

The original link: mp.weixin.qq.com/s/pR7fY0eK4…

 

Features overview

Here are some of the new features introduced in Java 9. A more detailed description of the new Java 9 features can be found here.

  • REPL (JShell)

  • Factory methods for immutable sets

  • Module system

  • Interface support for privatization

  • Diamond operator upgrade

  • Optional improvement

  • The Stream API improvements

  • Reactive Streams

  • Process API

  • Upgrade of the Try – With – Resources

  • HTTP / 2

  • Jar packages compatible with multiple versions

  • other

    • Improve application security
    • Unified JVM Journal
    • G1 is set as the default garbage collector
    • String underlying storage structure changed
    • CompletableFuture API improvements
    • New I/O flow features
    • JavaScript engine Nashorn improved
    • Identifiers add restrictions
    • The improved Javadoc
    • Improved @deprectaed annotation
    • Multiresolution image API
    • Handle to the variable
    • Improved Method Handle
    • AOT is compiled ahead of time

Java 9 REPL (JShell)

What is a REPL and why was it introduced

REPL, short for read-evaluate-print-loop. The features and benefits of the Scala language have attracted the attention of Oracle, which is trying to integrate most of Scala’s functionality into Java. This is already partially done in Java 8, such as Lambda expressions.

One of Scala’s best features is the REPL, which is a command-line interface and Scala interpreter for executing Scala programs. Since you don’t need to start an extra IDE (just a command line), it has the unique advantage of reducing the learning curve and simplifying running test code.

Java REPL, also known as JShell, was introduced in Java 9.

JShell basis

Open the command prompt, make sure you have Java 9 or higher, type jshell, and we’re happy to use it.

Here’s a simple demonstration:

wmyskxz:~ wmyskxz$ jshell 
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro

jshell> 

jshell> System.out.println("Hello World");
Hello World

jshell> String str = "Hello JShell!"
str ==> "Hello JShell!"

jshell> str
str ==> "Hello JShell!"

jshell> System.out.println(str)
Hello JShell!

jshell> int counter = 0
counter ==> 0

jshell> counter++
$6 ==> 0

jshell> counter
counter ==> 1

jshell> counter+5
$8 ==> 6
Copy the code

You can also define and execute class methods in the Java Shell:

jshell> class Hello {
   ...> public static void sayHello() {
   ...> System.out.print("Hello");
   ...> }
   ...> }
|  created class Hello

jshell> Hello.sayHello()
Hello
jshell> 
Copy the code

Java REPL – Help and exit

To get the help portion of the Jshell tool, use the /help command. To exit from jshell, use the /exit command (or simply use Ctrl + D to exit).

jshell> /help
|  Type a Java language expression, statement, or declaration.
|  Or type one of the following commands:
|  /list [<name or id>|-all|-start]
|   list the source you have typed
|  /edit <name or id>
...

jshell> /exit
|  Goodbye
wmyskxz:~ wmyskxz$ 
Copy the code

Factory method for immutable sets

Java 9 has added some handy factory methods for creating immutable List, Set, Map, and map.Entry objects.

In Java SE 8 and earlier, if we wanted to create an empty immutable or immutable list, we used the unmodifiableList() method of the Collections class to do so:

List<String> list = new ArrayList<>(); List.add (" public "); List.add (" I don't have three hearts "); List.add (" focus on walking "); List<String> immutableList = Collections.unmodifiableList(list);Copy the code

As you can see, we need to go through a lot of tedious and tedious steps to create a non-empty immutable list. To overcome this, Java 9 introduces the following useful overloaded methods in the List interface:

static <E> List<E> of(E e1) static <E> List<E> of(E e1,E e2) static <E> List<E> of(E e1,E e2,E e3) static <E> List<E> of(E e1,E e2,E e3,E e4) static <E> List<E> of(E e1,E e2,E e3,E e4,E e5) static <E> List<E> of(E e1,E e2,E e3,E e4,E e5,E  e6) static <E> List<E> of(E e1,E e2,E e3,E e4,E e5,E e6,E e7) static <E> List<E> of(E e1,E e2,E e3,E e4,E e5,E e6,E e7,E e8) static <E> List<E> of(E e1,E e2,E e3,E e4,E e5,E e6,E e7,E e8,E e9) static <E> List<E> of(E e1,E e2,E e3,E e4,E  e5,E e6,E e7,E e8,E e9,E e10)Copy the code

And the number of variable arguments:

static <E> List<E> of(E... elements)  
Copy the code

You can see Java 9 before and after:

List<String> List = new ArrayList<>(); List.add (" public "); List.add (" I don't have three hearts "); List.add (" focus on walking "); List<String> unmodifiableList = Collections.unmodifiableList(list); List<String> List = new ArrayList<>() {{add(" public id "); Add (" I don't have three hearts "); Add (" Focus on walking "); }}; List<String> unmodifiableList = Collections.unmodifiableList(list); List<String> unmodifiableList = list. of(" public number ", "I do not have three hearts "," focus on the List ");Copy the code

(PS: Set is similar to Map, and Map has two sets of methods: of() and ofEntries(), which are used to create Immutable Map objects and Immutable map.entry objects, respectively)

In addition, Java 9 can directly print the contents of a collection, whereas previously you had to walk through the collection to get all its elements, which is a big improvement.

Properties of immutable sets

Immutable means unchangeable. They usually have the following characteristics:

1. We cannot add, modify, or delete elements;

2, if you try to execute on them to add/delete/update operations, will be UnsupportedOperationException exceptions, as shown below:

jshell> immutableList.add("Test")
|  java.lang.UnsupportedOperationException thrown: 
|        at ImmutableCollections.uoe (ImmutableCollections.java:68)
|        at ImmutableCollections$AbstractImmutableList.add (ImmutableCollections.java:74)
|        at (#2:1)
Copy the code

3. Immutable sets do not allow null elements;

A NullPointerException exception will be raised if you attempt to create a null element.

Jshell > List > String > immutableList = List. Of (" public ", "I don't have three hearts", "pay attention to go up", null) | Java lang. NullPointerException thrown: | at Objects.requireNonNull (Objects.java:221) | at ImmutableCollections$ListN. (ImmutableCollections.java:179) | at List.of (List.java:859) | at (#4:1)Copy the code

5, if you try to add null elements, we get UnsupportedOperationException exceptions, as shown below:

jshell> immutableList.add(null)
|  java.lang.UnsupportedOperationException thrown: 
|        at ImmutableCollections.uoe (ImmutableCollections.java:68)
|        at ImmutableCollections$AbstractImmutableList.add (ImmutableCollections.java:74)
|        at (#3:1)
Copy the code

6. Collections can be serialized if all elements are serializable;

Module system

The Java module system is a new concept introduced by Oracle in Java 9. Initially, it started the project as part of the Java SE 7 Release, but it was delayed to Java SE 8 and then delayed again due to major changes. It was finally released with Java SE 9 in September 2017.

Why a modular system?

As the code base gets larger, the chances of creating complex, tangled “spaghetti code” multiply. There are several basic problems with delivering Java applications in Java 8 or earlier:

  1. It is difficult to really encapsulate the code, and there is no concept of explicit dependencies between different parts of the system (JAR files). Each public class can be accessed by any other public class on the CLASspath, resulting in unintentional use of classes that should not be public apis.
  2. Again, the classpath itself is problematic: how do you know if all the required jars exist, or if there are duplicate entries?
  3. In addition, the JDK is too large, and JAR files such as rt.jar * (rt.jar is the class file of all the classes seen in the Java Doc) * cannot even be used in small devices and applications: As a result, our applications and devices could not support better performance — packaged applications were too large — and it was difficult to test and maintain applications.

Module system solves these problems.

What is the Java 9 module system?

A module is a self-describing collection of code, data, and some resources. It is a set of packages related to code, data, and resources.

Each module contains only a set of related code and data to support the single responsibility principle (SRP).

 

The main goal of the Java 9 module system is to support Java modular programming. (We’ll take a look at modular programming below.)

Compare JDK 8 and JDK 9

We know what JDK software contains. After installing the JDK 8 software, we can see several directories in the Java Home folder, such as bin, jre, lib, etc.

However, Oracle changes the folder structure somewhat differently in Java 9, as shown below.

 

The JDK 9 here does not include the JRE. In JDK 9, the JRE is divided into a separate distribution folder. The JDK 9 software includes a new folder, “JMOds,” that contains a set of Java 9 modules. In JDK 9, there are no rt.jar and tools.jar. (as shown below)

 

Note: As of today, JMODS contains 95 modules. (The final version may have more)

Compare Java 8 and Java 9 applications

We have developed many Java applications using Java 5, Java 6, Java 7, or Java 8, and we know that for Java 8 or earlier applications, the top-level component is Package:

 

Java 9 applications are not much different from this. It has just introduced new components called “modules” and called module descriptors (module-info.java) :

 

Just as Java 8 applications use Packages as top-level components, Java 9 applications use Modules as top-level components.

Note: Each Java 9 module has only one module and one module descriptor. Unlike the Java 8 package, you cannot create multiple modules in a single module.

The HelloModule sample program

As developers, we start learning new concepts or programming languages with the “HelloWorld” program. In the same way, we started learning about the new Java 9 concept of “modular programming” through “HelloModule” module development.

Step 1: Create an empty Java project

If you don’t want to name it extra, you can just go Next all the way:

 

Step 2: Create the HelloModule module

Right-click the project and create a new Module named com.wmyskz.core

 

Create a package named module.hello under the SRC folder of the new Module.

. └ ─ ─ com. Wmyskxz. Core └ ─ ─ the SRC └ ─ ─ the module └ ─ ─ the helloCopy the code

Step 3: Write Hellomodule.java

Create a new HelloModule file under the package you just created and write the code for the test:

package module.hello;

public class HelloModule {
  
    public void sayHello() {
        System.out.println("Hello Module!");
    }
}
Copy the code

Step 4: Write the Module descriptor for the Module

In IDEA, you can create a module-info.java file by right clicking the SRC folder:

 

Write the module-info.java file to expose the contents of our package module.hello (for use by other modules) :

module com.wmyskxz.core {
    exports module.hello;
}
Copy the code

The module keyword is followed by the name of our module, whose exports name identifies the package we want to expose. The file directory structure is as follows:

. └ ─ ─ com. Wmyskxz. Core └ ─ ─ the SRC ├ ─ ─ the module │ └ ─ ─ the hello │ └ ─ ─ HelloModule. Java └ ─ ─ the module - info. JavaCopy the code

Step 5: Write the client in the same way

Using the same method above, we create a Module for com.wmyskz.client in the project root directory, create a new Module. Client package directory, and create our HelloModuleClient file that looks like this:

// HelloModuleClient.java
package module.client;

public class HelloModuleClient {

    public static void main(String[] args) {

    }
}
Copy the code

If we wanted to call the HelloModule class directly, we would find that IDEA has no message, that is, we would not be able to refer directly to the..

We need to explicitly introduce the com.wmyskxz.core module we just exposed in the module descriptor (also creating the module-info.java file in the SRC directory) :

module com.wmyskxz.client {
    requires com.wmyskxz.core;
}
Copy the code

(PS: After writing in IDEA, manual Alt + Enter is required to introduce module dependency)

With that done, we can happily use the HelloModule file in the previous HelloModuleClient:

package module.client; import module.hello.HelloModule; public class HelloModuleClient { public static void main(String[] args) { HelloModule helloModule = new HelloModule(); helloModule.sayHello(); }}Copy the code

The project structure at this time:

. ├ ─ ─ com. Wmyskxz. Client │ └ ─ ─ the SRC │ ├ ─ ─ the module │ │ └ ─ ─ client │ │ └ ─ ─ HelloModuleClient. Java │ └ ─ ─ the module - info. Java └ ─ ─ Com. Wmyskxz. Core └ ─ ─ the SRC ├ ─ ─ the module │ └ ─ ─ the hello │ └ ─ ─ HelloModule. Java └ ─ ─ the module - info. JavaCopy the code

Step 6: Run the tests

Run code:

Hello Module!
Copy the code

Success!

Summary of module system

As we can see from the example above, we can specify which packages we want to export and reference, and no one can inadvertently use classes from packages that do not want to be exported.

The Java platform itself has modularized the JDK with its own module system. When starting a modular application, the JVM verifies that all modules can be parsed based on the requires statement, which is much safer than a fragile classpath. Modules enable you to better build applications by enforcing encapsulation and explicit dependencies.

The interface supports private methods

In Java 8, we can use the default and static methods to provide method implementations in Interfaces. However, we cannot create private methods in the interface.

To avoid redundant code and improve reuse, Oracle Corp will introduce private methods in the Java SE 9 interface. Since Java SE 9, we have been able to write private and private static methods in interfaces using the private keyword.

These private methods are just like any other class private method; there is no difference between them. Here’s a demo:

Public interface FilterProcess<T> {public static final String a ="22"; boolean process(T t); Void love(){system.out.println ("java8 default method "); } static void haha(){system.out.println (" Java8 feature static method "); Private void java9(){}}Copy the code

5. Diamond operator upgrade

As we know, Java SE 7 introduced a new feature: the Diamond operator improves readability by avoiding redundant code and verbosity. However, in Java SE 8, Oracle Corp (Java Library developer) found some limitations in using the Diamond operator with anonymous inner classes. They have resolved these issues and released it as part of Java 9.

// Java6 <String,String> map7 = new HashMap<String,String>(); // Java7 and 8 <> have no data type Map<String,String> map8 = new HashMap<>(); Map<String,String> map9 = new HashMap<>(){};Copy the code

Optional improvement

In Java SE 9, Oracle Corp introduced the following three methods to improve the Optional feature.

  • The stream ();
  • IfPresentOrElse ();
  • or()

The optional stream() method

If a value exists in the given Optional object, the stream() method returns a sequential stream with that value. Otherwise, it returns an empty stream.

The stream() method added in Java 9 allows us to process optional objects lazily. Here’s a demonstration:

jshell> long count = Stream.of( ... > Optional.of(1), ... > Optional.empty(), ... > Optional.of(2) ... > ).flatMap(Optional::stream) ... > .count(); . > System.out.println(count); . > count ==> 2 2Copy the code

Optiona l The stream contains three elements, of which only two have values. After using flatMap, the result stream contains two values.

Optional ifPresentOrElse() method

We know that in Java SE 8, we can use the ifPresent(), isPresent(), and orElse() methods to examine and perform functions on Optional objects. This process can be tedious, and Java SE 9 introduces a new approach to overcome this problem.

Here’s an example:

jshell> Optional<Integer> opt1 = Optional.of(4)
opt1 ==> Optional[4]

jshell> opt1.ifPresentOrElse( x -> System.out.println("Result found: " + x), () -> System.out.println("Not Found."))
Result found: 4

jshell> Optional<Integer> opt2 = Optional.empty()
opt2 ==> Optional.empty

jshell> opt2.ifPresentOrElse( x -> System.out.println("Result found: " + x), () -> System.out.println("Not Found."))
Not Found.
Copy the code

The optional or() method

In Java SE 9, the or() method is a handy return value. If Optional contains a value, the original value is returned, otherwise the specified value is returned. The or() method specifies the Supplier as the default. Here is the definition of the API:

public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)
Copy the code

Here is a demonstration of the value case:

jshell> Optional<String> opStr = Optional.of("Rams")
opStr ==> Optional[Rams]

jshell> import java.util.function.*

jshell> Supplier<Optional<String>> supStr = () -> Optional.of("No Name")
supStr ==> $Lambda$67/222624801@23faf8f2

jshell> opStr.or(supStr)
$5 ==> Optional[Rams]
Copy the code

Here is a demonstration of the empty case:

jshell> Optional<String> opStr = Optional.empty()
opStr ==> Optional.empty

jshell> Supplier<Optional<String>> supStr = () -> Optional.of("No Name")
supStr ==> $Lambda$67/222624801@23faf8f2

jshell> opStr.or(supStr)
$7 ==> Optional[No Name]
Copy the code

7. Stream API improvement

The Streams API has long been one of the best improvements to the Java standard library. In Java 9, the Stream interface added four useful methods: dropWhile, takeWhile, ofNullable, and iterate. So let’s do it separately.

TakeWhile () method

In the Stream API, the takeWhile() method returns the longest prefix element that matches the Predicate condition.

It takes the Predicate interface as an argument. Predicate is a Boolean expression that returns true or false. The behavior is different for ordered and disordered flows. Let’s explore this with some simple examples below.

Stream API definition:

default Stream<T> takeWhile(Predicate<? super T> predicate)
Copy the code

Ordered flow example: –

Jshell > Stream<Integer> Stream = stream.of (1,2,3,4,5,6,7,8,9,10) Stream ==> java.util.stream.ReferencePipeline$Head@55d56113 jshell> stream.takeWhile(x -> x < 4).forEach(a -> System.out.println(a)) 1 2 3Copy the code

An example of an out-of-order flow is: –

Jshell > Stream<Integer> Stream = stream.of (1,2,4,5,3,6,7,8,9,10) Stream ==> java.util.stream.ReferencePipeline$Head@55d56113 jshell> stream.takeWhile(x -> x < 4).forEach(a -> System.out.println(a)) 1 2Copy the code

From the example above, we can see that the takeWhile() method stops traversing down when it encounters the first element that returns false.

DropWhile () method

Corresponding to takeWhile(), dropWhile() is used to remove the longest prefix element that matches the condition and return the rest.

Stream API definition:

default Stream<T> dropWhile(Predicate<? super T> predicate)
Copy the code

Ordered flow example: –

Jshell > Stream<Integer> Stream = stream.of (1,2,3,4,5,6,7,8,9,10) Stream ==> java.util.stream.ReferencePipeline$Head@55d56113 jshell> stream.dropWhile(x -> x < 4).forEach(a -> System.out.println(a)) 4 5 6 7 8 9 10Copy the code

An example of an out-of-order flow is: –

Jshell > Stream<Integer> Stream = stream.of (1,2,4,5,3,6,7,8,9,10) Stream ==> java.util.stream.ReferencePipeline$Head@55d56113 jshell> stream.dropWhile(x -> x < 4).forEach(a -> System.out.println(a)) 4 5 3 6 7 8 9 10Copy the code

Iterate () method

In the Stream API, the iterate() method can return a Stream of elements that begins with initialValue (the first argument), matches the Predicate (the second argument), and uses the third argument to make the next element.

Stream API definition:

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)
Copy the code

IntStream Iteration example: –

jshell> IntStream.iterate(2, x -> x < 20, x -> x * x).forEach(System.out::println)
2
4
16
Copy the code

Here, the entire element stream starts with the number 2, ends with the condition < 20, and in the next iteration, the increment value is the square of its own value.

In Java SE 8, the auxiliary filter condition is required to do this:

jshell> IntStream.iterate(2, x -> x * x).filter(x -> x < 20).forEach(System.out::println)
2
4
16
Copy the code

OfNullable () method

In the Stream API, ofNullable() returns a sequential Stream containing a single element (if not null), or an empty Stream otherwise.

Java SE 9 Example: –

jshell> Stream<Integer> s = Stream.ofNullable(1)
s ==> java.util.stream.ReferencePipeline$Head@1e965684

jshell> s.forEach(System.out::println)
1

jshell> Stream<Integer> s = Stream.ofNullable(null)
s ==> java.util.stream.ReferencePipeline$Head@3b088d51

jshell> s.forEach(System.out::println)

jshell>
Copy the code

Note: Stream subinterfaces (e.g. IntStream, LongStream, etc..) Both inherit the above four methods.

Reactive Streams

The idea of reactive programming has recently gained wide popularity. There are popular reaction libraries RxJava and Reactor on the Java platform. The starting point of the reactive flow specification is to provide an asynchronous flow processing specification with non-blocking backpressure.

The Java SE 9 Reactive Streams API is a publish/subscribe framework designed to make asynchronous, scalable, and parallel applications very easy to implement in the Java language.

 

(It’s clear from the figure above that the Processor can act as both a subscriber and a publisher.)

The core of the reactive Flow specification interface has been added to the Java Java9. Util. Concurrent. The Flow in the class.

Reaction flow example

Let’s start with a simple example where we will implement the Flow API Subscriber interface and create publishers and send messages using SubmissionPublisher.

Streaming data

Suppose we have an Employee class that will be used to create flow messages to be sent from the publisher to the subscriber.

package com.wmyskxz.reactive.beans; public class Employee { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Employee(int i, String s) { this.id = i; this.name = s; } public Employee() { } @Override public String toString() { return "[id=" + id + ",name=" + name + "]"; }}Copy the code

We also have a utility class that creates a list of employees for us:

package com.wmyskxz.reactive.streams; import com.wmyskxz.reactive.beans.Employee; import java.util.List; Public class EmpHelper {public static List<Employee> getEmps() {return list.of (new Employee(1, "I don't have three hearts "), New Employee(2, "three hearts "), new Employee(3," heart "); }}Copy the code

The subscriber

package com.wmyskxz.reactive.streams; import com.wmyskxz.reactive.beans.Employee; import java.util.concurrent.Flow.Subscriber; import java.util.concurrent.Flow.Subscription; public class MySubscriber implements Subscriber<Employee> { private Subscription subscription; private int counter = 0; @Override public void onSubscribe(Subscription subscription) { System.out.println("Subscribed"); this.subscription = subscription; this.subscription.request(1); // requesting data from publisher System.out.println("onSubscribe requested 1 item"); } @Override public void onNext(Employee item) { System.out.println("Processing Employee " + item); counter++; this.subscription.request(1); } @Override public void onError(Throwable e) { System.out.println("Some error happened"); e.printStackTrace(); } @Override public void onComplete() { System.out.println("All Processing Done"); } public int getCounter() { return counter; }}Copy the code
  • The Subscription variable preserves references so that requests can be made in the onNext method.
  • The counter variable to keep a count of the number of items processed, notice that its value is increased in the onNext method. We’ll use it in our main method to wait for execution to complete and then terminate the main thread.
  • Call the subscription request in the onSubscribe method to begin processing. Also note that onNext calls this method again after the project has been processed, requiring the publisher to process the next project.
  • OnError and onComplete don’t have much effect here, but in real-world scenarios, they should be used when errors occur or resource cleanup is successfully processed when corrective action is completed.

Reaction flow test procedure

We used SubmissionPublisher as an example, so let’s take a look at the test program for the reaction flow implementation:

package com.wmyskxz.reactive.streams; import com.wmyskxz.reactive.beans.Employee; import java.util.List; import java.util.concurrent.SubmissionPublisher; public class MyReactiveApp { public static void main(String[] args) throws InterruptedException { // Create Publisher SubmissionPublisher<Employee> publisher = new SubmissionPublisher<>(); // Register Subscriber MySubscriber subs = new MySubscriber(); publisher.subscribe(subs); List<Employee> emps = EmpHelper.getEmps(); // Publish items System.out.println("Publishing Items to Subscriber"); for (Employee employee : emps) { publisher.submit(employee); Thread.sleep(1000); // simulate true environment } // logic to wait till processing of all messages are over while (emps.size() ! = subs.getCounter()) { Thread.sleep(10); } // close the Publisher publisher.close(); System.out.println("Exiting the app"); }}Copy the code

The most important part of the code above is the subscribe and submit method calls. Also, we should close the publisher after use to avoid any memory leaks.

When we execute the above program, we get the following output:

Subscribed onSubscribe requested 1 item Publishing Items to Subscriber Processing Employee [id=1,name= I don't have three hearts] Processing Employee [ID =2,name= three hearts] Processing Employee [ID =3,name= heart] Withdraw the app All Processing DoneCopy the code

All of the above code can be found under demo-project in the “MoreThanJava” project: Portals

In addition, if you want to know more, please visit: www.journaldev.com/20723/java-.

9. Process API

Java 9 adds the ProcessHandle interface to manage native processes, especially long-running processes.

After starting a Process with the ProcessBuilder, you can get an instance of the ProcessHandle object through the process.tohandle () method. You can use ProcessHandle to obtain basic information about the processhandle. Info process, such as command line parameters, executable file paths, and startup time. The onExit() method of ProcessHandle returns a CompletableFuture object that can perform a custom action at the end of the process.

Here is an example of the process API in use:

final ProcessBuilder processBuilder = new ProcessBuilder("top") .inheritIO(); final ProcessHandle processHandle = processBuilder.start().toHandle(); processHandle.onExit().whenCompleteAsync((handle, throwable) -> { if (throwable == null) { System.out.println(handle.pid()); } else { throwable.printStackTrace(); }});Copy the code

Upgrade try-with-resources

As we know, Java SE 7 introduced a new exception handling structure: try-with-Resources to automatically manage Resources. The main goal of this new statement is “automated better resource management”.

Java SE 9 will make some improvements to this statement to avoid more verbosity and improve readability.

Java SE 7 example

void testARM_Before_Java9() throws IOException{ BufferedReader reader1 = new BufferedReader(new FileReader("journaldev.txt")); try (BufferedReader reader2 = reader1) { System.out.println(reader2.readLine()); }}Copy the code

Java SE 9 example:

void testARM_Java9() throws IOException{ BufferedReader reader1 = new BufferedReader(new FileReader("journaldev.txt")); try (reader1) { System.out.println(reader1.readLine()); }}Copy the code

11. HTTP / 2

Java 9 provides a new way to perform HTTP calls. The alternative to this expiration expiration is the old HttpURLConnection. The API also supports WebSockets and HTTP / 2. One thing to note: The new HttpClient API is available in Java 9 in the form of what is called Incubator Module. This means that the API is not yet 100% guaranteed. However, with the advent of Java 9, you can already start using the API:

HttpClient client = HttpClient.newHttpClient();

HttpRequest req =
   HttpRequest.newBuilder(URI.create("http://www.google.com"))
              .header("User-Agent","Java")
              .GET()
              .build();


HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandler.asString());
Copy the code

Multi-version compatible Jar package

The multi-version-compatible JAR feature lets you create the version of class that you choose to use when running the library only in a particular version of your Java environment.

Specify the compiled version with the –release argument.

The MANIFEST.MF file in the meta-INF directory has a new attribute:

Multi-Release: true
Copy the code

In the meta-INF directory, a version directory is added. If you want to support Java 9, the versions directory will have the 9 directory.

Multirelease. Jar ├ ─ ─ meta-inf │ └ ─ ─ versions │ └ ─ ─ nine │ └ ─ ─ multirelease │ └ ─ ─ Helper. Class ├ ─ ─ multirelease ├ ─ ─ Helper. Class └ ─ ─ the Main classCopy the code

Specific examples can view here: www.runoob.com/java/java9-…

Other updates

Improve application security

Java 9 has four new SHA-3 hashing algorithms, SHA3-224, SHA3-256, SHA3-384, and SHA3-512. In addition also increased by Java. Security. SecureRandom generated using DRBG strong random Numbers of the algorithm. An example of the sha-3 hash algorithm is given below:

final MessageDigest instance = MessageDigest.getInstance("SHA3-224");
final byte[] digest = instance.digest("".getBytes());
System.out.println(Hex.encodeHexString(digest));
Copy the code

Unified JVM Journal

In Java 9, the JVM has a unified logging system that allows you to control logging for all components on the JVM using the new command-line option -xlog. The logging system can set the label, level, modifier and output target of the output log message.

G1 is set as the default collector implementation

Java 9 removes garbage collector configuration combinations that were deprecated in Java 8 (such as ParNew + SerialOld) and makes G1 the default garbage collector implementation (for both 32-bit and 64-bit systems). In addition, the CMS garbage collector has been declared deprecated. Java 9 also adds a number of diagnostic commands that can be invoked through JCMD.

String underlying storage structure changed

 

Char [] char[] char[]

To adopt a more space-efficient internal representation of strings, the internal representation of the String class was changed from a UTF-16 char array to an array of bytes with encoded tag fields. The new String class stores characters encoded as ISO-8859-1 / Latin-1 (one byte per character) or UTF-16 (two bytes per character) based on the String content. The encoding flag will indicate which encoding to use.

(PS: In addition, most of the internal methods also have more judgment of character encoding)

CompletableFuture API improvements

In Java SE 9, Oracle Corp will improve the CompletableFuture API to address some of the issues raised in Java SE 8. They will be added to support some latencies and timeouts, some utility methods, and better subclassing.

Executor exe = CompletableFuture.delayedExecutor(50L, TimeUnit.SECONDS);
Copy the code

Here delayExecutor() is a static utility method that returns a new Executor that submits the task to the default Executor after a given delay.

New I/O flow features

New methods have been added to the java.io.InputStream class to read and copy data contained in InputStream.

  • ReadAllBytes: Reads all remaining bytes in InputStream.
  • ReadNBytes: Reads a specified number of bytes from InputStream into an array.
  • TransferTo: Reads all bytes in InputStream and writes them to the specified OutputStream.

Here is an example of the new method in use:

public class TestInputStream { private InputStream inputStream; private static final String CONTENT = "Hello World"; @Before public void setUp() throws Exception { this.inputStream = TestInputStream.class.getResourceAsStream("/input.txt"); } @Test public void testReadAllBytes() throws Exception { final String content = new String(this.inputStream.readAllBytes()); assertEquals(CONTENT, content); } @Test public void testReadNBytes() throws Exception { final byte[] data = new byte[5]; this.inputStream.readNBytes(data, 0, 5); assertEquals("Hello", new String(data)); } @Test public void testTransferTo() throws Exception { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); this.inputStream.transferTo(outputStream); assertEquals(CONTENT, outputStream.toString()); }}Copy the code

JavaScript engine Nashorn improved

Nashorn is the new JavaScript engine introduced in Java 8. Nashorn in Java 9 has implemented several new features in the ECMAScript 6 specification, including template strings, binary and octal literals, iterators, and for.. Of loops and arrow functions. Nashorn also provides an API to parse ECMAScript source code into an Abstract Syntax Tree (AST) that can be used to analyze ECMAScript source code.

Identifiers add restrictions

String _ = “hello; Such identifiers can be used, but have not been allowed since JDK 9.

The improved Javadoc

Sometimes small things can make a big difference. Have you been using Google to find the right Javadoc page, as I have? It will no longer be needed. Javadoc now includes search capabilities in the API documentation itself. In addition, Javadoc output is now HTML 5 compatible. Also, you’ll notice that each Javadoc page contains information about which JDK module the class or interface comes from.

 

Improved @deprecated annotation

The @deprecated annotation can mark Java API status, which can be one of the following:

  • Using it is risky and can lead to errors
  • May not be compatible in future releases
  • May be removed in future releases
  • A better and more efficient scheme has replaced it.

Annotations in Java 9 add two new elements: since and forRemoval.

  • Since: Element specifies the deprecated version of the annotated API element.
  • ForRemoval: element Indicates that the ANNOTATION API element will be removed in a future release and the API should be migrated.

The following example is the Java 9 documentation for Boolean classes, in which the @deprecated annotation uses the since attribute: Boolean Class.

 

JavaDoc specification interception for Boolean

Multiresolution image API

In Java SE 9, Oracle Corp will introduce a new Multi-resolution Image API. The important interface in this API is the MultiResolutionImage. Available in the java.awt.image package.

MultiResolutionImage encapsulates a set of images with different heights and widths (that is, different resolutions) and allows us to query them on demand.

Handle to the variable

VarHandle is a strongly typed reference to a variable, or a parameterized family of variables, including static fields, non-static fields, array elements, etc. VarHandle supports variable access under different access models, including simple read/write access. Volatile read/write access, and CAS access.

VarHandle has huge advantages over traditional concurrent operations on variables. After the introduction of VarHandle in JDK 9, variable access in JUC packages is basically using VarHandle, such as variables used in CLH queues in AQS.

Improved Method Handle

Class. Java lang. Invoke. MethodHandles added more static method to create different types of method to handle:

  • ArrayConstructor: Creates an array of the specified type.
  • ArrayLength: Gets the size of an array of the specified type.
  • VarHandleInvoker and varHandleExactInvoker: Call the access-mode methods in VarHandle.
  • Zero: Returns a default value for a type.
  • Empty: Returns the default value for the return value type of MethodType.
  • Loop, countedLoop, iteratedLoop, whileLoop and doWhileLoop: Create different types of loops, including for loops, while loops, and do-while loops.
  • TryFinally: Encapsulates calls to method handles in try-finally statements.

AOT is compiled ahead of time

With Java 9, and JEP 295 in particular, the JDK gets the Ahead-of-time (AOT) compiler JAOTC. The compiler uses the OpenJDK project Graal for back-end code generation for the following reasons:

JIT compilers are fast, but Java programs can be so large that it takes a long time for the JIT to fully warm up. Seldom-used Java methods may not compile at all, and performance may degrade due to repeated explain calls

The original link: openjdk.java.net/jeps/295

The Graal OpenJDK project demonstrates that a compiler written in pure Java can generate highly optimized code. With this AOT compiler and Java 9, you can manually compile Java code ahead of time. This means generating machine code before execution, rather than at run time as JIT compilers do, which was the first experimental approach.

# using the new AOT compiler (jaotc is bundeled within JDK 9 and above) jaotc --output libHelloWorld.so HelloWorld.class  jaotc --output libjava.base.so --module java.base # with Java 9 you have to manually specify the location of the native  code java -XX:AOTLibrary=./libHelloWorld.so,./libjava.base.so HelloWorldCopy the code

This improves startup time because the JIT compiler does not have to intercept the execution of the program. The main disadvantage of this approach is that the generated machine code depends on the platform on which the program is running (Linux, MacOS, Windows…). . This can cause AOT-compiled code to be bound to a particular platform.

 

More…

A complete feature list: openjdk.java.net/projects/jd…

The resources

  1. Its official documentation – openjdk.java.net/projects/jd…
  2. Java 9 Modules | JournalDev – www.journaldev.com/13106/java-…
  3. The JDK 9 new features, rounding – my.oschina.net/mdxlcj/blog…
  4. Java SE 9: Stream API Improvements – www.journaldev.com/13204/javas…
  5. Nine NEW FEATURES IN JAVA 9 – www.pluralsight.com/blog/softwa…
  6. Java 9 new features overview | IBM – developer.ibm.com/zh/articles…
  7. Java version 9 more compatible with the jar package | novice tutorial – www.runoob.com/java/java9-…