Introduction to Java 17 new features (LTS)

Posted by stueee on Mon, 08 Nov 2021 18:31:42 +0100

>Like and see again, unlimited power. Hello world:) wechat search Program ape Alan 」. > > this paper Github.com/niumoo/JavaNotes and Unread code blog Has been included, there are many knowledge points and series of articles.

Java 17 was officially released on September 14, 2021. Java 17 is a long-term support (LTS) version. This update brings 14 new functions.

OpenJDK Java 17 Download: https://jdk.java.net/archive/

OpenJDK Java 17 documentation: https://openjdk.java.net/projects/jdk/17/

<!-- more -->

JEP describe
JEP 306 Restore always strict floating point semantics
JEP 356 Enhanced pseudo-random number generator
JEP 382 Using the new macOS rendering Library
JEP 391 Support Mac OS / aarch64 architecture
JEP 398 Delete enabled Applet API
JEP 403 Stronger JDK internal packaging
JEP 406 Switch pattern matching (Preview)
JEP 407 Remove RMI Activation
JEP 409 Sealed Classes
JEP 410 JEP 401: removing experimental AOT and JIT compilers
JEP 411 Discard Security Manager
JEP 412 External functions and memory API s (incubators)
JEP 414 Vector API (second incubator)
JEP 415 Specifies the deserialization filter for the context

>This article belongs to New Java features tutorial Series, which will introduce the new functions of each version of Java. You can click to browse.

1. JEP 306: restore always strict floating point semantics

Since the strict floating-point semantics are restored, it means that the strict floating-point semantics are always before a certain point in time. In fact, before Java SE 1.2, all floating-point calculations were strict, but in the original situation, too strict floating-point calculations run on the popular x86 architecture and x87 floating-point protocol processor, which requires a lot of additional instruction overhead. Therefore, starting from Java SE 1.2, the keyword strictfp (strict float point) needs to be used manually To enable strict floating-point calculations.

However, today in 2021, great changes have taken place in the hardware, and the original problem no longer exists. Therefore, starting from Java 17, the feature of always strict floating-point semantics has been restored.

Extension: strictfp is a keyword in Java. Most people may not have noticed it. It can be used on classes, interfaces or methods. float and double expressions in the part modified by strictfp will perform strict floating-point calculation.

The following is an example in which testStrictfp() is modified by strictfp.

package com.wdbyte;

public class Main {
    public static void main(String[] args) {
        testStrictfp();
    }

    public strictfp static void testStrictfp() {
        float aFloat = 0.6666666666666666666f;
        double aDouble = 0.88888888888888888d;
        double sum = aFloat + aDouble;
        System.out.println("sum: " + sum);
    }
}

2. JEP 356: enhanced pseudo-random number generator

A new interface type and implementation are added to the pseudo random number generator RPNG (pseudo random number generator), which makes it much easier to use various PRNG algorithms in the code.

This time, the RandomGenerator interface is added to provide a unified API for all PRNG algorithms, and different types of PRNG object streams can be obtained. At the same time, a new class RandomGeneratorFactory is provided to construct various RandomGenerator instances. ServiceLoader.provider is used in RandomGeneratorFactory to load various PRNG implementations.

The following is a usage example: randomly select a PRNG algorithm to generate 5 random numbers within 10.

package com.wdbyte.java17;

import java.util.Date;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
import java.util.stream.Stream;

/**
 * @author niulang
 */
public class JEP356 {

    public static void main(String[] args) {
        RandomGeneratorFactory<randomgenerator> l128X256MixRandom = RandomGeneratorFactory.of("L128X256MixRandom");
        // Use timestamp as random number seed
        RandomGenerator randomGenerator = l128X256MixRandom.create(System.currentTimeMillis());
        for (int i = 0; i &lt; 5; i++) {
            System.out.println(randomGenerator.nextInt(10));
        }
    }
}

Get output:

7
3
4
4
6

You can also traverse all PRNG algorithms.

RandomGeneratorFactory.all().forEach(factory -&gt; {
    System.out.println(factory.group() + ":" + factory.name());
});

Get output:

LXM:L32X64MixRandom
LXM:L128X128MixRandom
LXM:L64X128MixRandom
Legacy:SecureRandom
LXM:L128X1024MixRandom
LXM:L64X128StarStarRandom
Xoshiro:Xoshiro256PlusPlus
LXM:L64X256MixRandom
Legacy:Random
Xoroshiro:Xoroshiro128PlusPlus
LXM:L128X256MixRandom
Legacy:SplittableRandom
LXM:L64X1024MixRandom

You can see that Legacy:Random is also included. The new API is compatible with the old Random method, so you can also use the new API to call the Random class to generate Random numbers.

// Using Random
RandomGeneratorFactory<randomgenerator> l128X256MixRandom = RandomGeneratorFactory.of("Random");
// Use timestamp as random number seed
RandomGenerator randomGenerator = l128X256MixRandom.create(System.currentTimeMillis());
for (int i = 0; i &lt; 5; i++) {
    System.out.println(randomGenerator.nextInt(10));
}

>Extended reading: Enhanced pseudo-random number generator

3. JEP 382: using the new macOS rendering Library

In order to improve the rendering performance of graphics, macOS abandoned the previous OpenGL rendering library and used Apple Metal instead in September 2018. Java 17 supports Apple Metal this update, but there are no changes to the API. These are internal modifications.

>Extended reading: macOS Mojave 10.14 Release NotesApple Metal

4. JEP 391: supports Mac OS / aarch64 architecture

The reason is that Apple announced in its WWDC speech in June 2020 that it would start a long-term plan to transition the Macintosh computer series from x64 to AArch64. Therefore, it is necessary to make JDK support macOS/AArch64 as soon as possible.

AArch64 support on Linux and already supported in Java 16 can be found in the previous articles.

>Extension: Introduction to new features of Java 16 - JEP 386 >

5. JEP 398: delete deprecated Applet API

Applet is a small application written in Java that can be embedded into HTML. The embedding method is through ordinary HTML tag syntax. Because it is already outdated, there are almost no scenarios to use.

Example: embed Hello.class

<applet code="Hello.class" height="200" width="200"></applet>

The Applet API has been marked obsolete in Java 9, and will now be completely deleted in Java 17.

6. JEP 403: stronger JDK internal packaging

As described in JEP 396 of Java 16, in order to improve the security of JDK, change the default mode of -- illegal access option from allow to deny. With this change, the JDK's internal package and API( Key internal API s Except) will no longer be turned on by default.

However, in Java 17, except sun.misc.Unsafe, the strong encapsulation mode inside JDK can not be opened by using -- illegal access command, except sun.misc.Unsafe API

Using the -- illegal access option in Java 17 will get a warning that the command has been removed.

➜  bin ./java -version
openjdk version "17" 2021-09-14
OpenJDK Runtime Environment (build 17+35-2724)
OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)
➜  bin ./java --illegal-access=warn
OpenJDK 64-Bit Server VM warning: Ignoring option --illegal-access=warn; support was removed in 17.0

>Extended reading: JEP 403: stronger JDK internal packagingIntroduction to new features of Java 16 >

7. JEP 406: type matching of switch (Preview)

Like instanceof, automatic conversion of type matching is added to switch.

Before using instanceof, you need to do the following:

if (obj instanceof String) {
    String s = (String) obj;    // grr...
    ...
}

Redundant type cast, and now:

if (obj instanceof String s) {
    // Let pattern matching do the work!
    ...
}

switch can use a similar method.

static String formatterPatternSwitch(Object o) {
    return switch (o) {
        case Integer i -&gt; String.format("int %d", i);
        case Long l    -&gt; String.format("long %d", l);
        case Double d  -&gt; String.format("double %f", d);
        case String s  -&gt; String.format("String %s", s);
        default        -&gt; o.toString();
    };
}

There is also a new way to judge null values.

// Before Java 17
static void testFooBar(String s) {
    if (s == null) {
        System.out.println("oops!");
        return;
    }
    switch (s) {
        case "Foo", "Bar" -&gt; System.out.println("Great");
        default           -&gt; System.out.println("Ok");
    }
}
// Java 17
static void testFooBar(String s) {
    switch (s) {
        case null         -&gt; System.out.println("Oops");
        case "Foo", "Bar" -&gt; System.out.println("Great");
        default           -&gt; System.out.println("Ok");
    }
}

>Extended reading: JEP 406: type matching of switch (Preview)

8. JEP 407: remove RMI Activation

RMI (Remote Method Invocation) Activation marked abolished in JEP 385 is removed, but other parts of RMI will not be affected.

JEP 385 of RMI Activation in Java 15 has been marked as obsolete and abandoned. So far, no adverse feedback has been received, so it is decided to officially remove it in Java 17.

>Extended reading: JEP 407: removing RMI Activation

9. JEP 409: Sealed Classes

Sealed Classes is proposed in JEP 360 in Java 15. JEP 397 in Java 16 is previewed again. Now it has become a formal function in Java 17. Compared with Java 16, there are no functional changes. I won't repeat the introduction here. For more information, please refer to the previous articles.

>Extended reading: Introduction to new features of Java 16JEP 409: Sealed Classes >

10. JEP 401: remove experimental AOT and JIT compilers

In JEP 295 of Java 9, an experimental pre compilation jaotc tool is introduced, but this feature is not very useful since the introduction of dependency, and requires a lot of maintenance work, so it is decided to delete this feature in Java 17.

Three JDK modules have been removed:

  1. jdk.aot - jaotc tool.
  2. Jdk.internal.vm.compiler - grail compiler.
  3. jdk.internal.vm.compiler.management

Some HotSpot codes related to AOT compilation are also removed:

  1. src/hotspot/share/aot — dumps and loads AOT code
  2. Additional code guarded by #if INCLUDE_AOT

11. JEP 411: discard Security Manager

Security Manager has been introduced in JDK 1.0, but it has never been the main means to protect the Java code of the server and client. In order to continue the development of Java, it is decided to abandon Security Manager and delete it in the near future.

@Deprecated(since="17", forRemoval=true)
public class SecurityManager {
	// ...
}

12. JEP 412: external function and memory API (incubation)

The new API allows Java developers to interact with code and data outside the JVM. By calling external functions, they can call local libraries without using JNI.

This is an incubation function; You need to add -- add modules jdk.initiator.foreign to compile and run Java code.

history

  • Java 14 JEP 370 The external memory access API (incubator) is introduced.
  • Java 15 JEP 383 The external memory access API (second incubator) is introduced.
  • Java 16 JEP 389 The external linker API (incubator) is introduced.
  • Java 16 JEP 393 The external memory access API (the third incubator) is introduced.
  • Java 17 JEP 412 External functions and memory API s (incubators) are introduced.

>Extended reading: JEP 412: external functions and memory API s (incubation)

13. JEP 414: Vector API (secondary incubation)

A new API is introduced into Java 16 for vector computing, which can be reliably compiled into a supported CPU architecture at runtime, so as to achieve better computing power.

Now, the performance of Vector API has been improved in Java 17, such as the operation of characters and the mutual conversion between byte vectors and Boolean arrays.

14. JEP 415: deserialization filter for specified context

Serialization in Java has always been a very important function. Without serialization, Java may not occupy the dominant position of the development language. Serialization makes remote processing easy and transparent, and also promotes the success of Java EE.

However, there are many problems with Java serialization. It will make almost all conceivable mistakes and bring continuous maintenance work to developers. However, it should be noted that the concept of serialization is not wrong. It is a completely reasonable idea to convert objects into the ability to transfer freely between JVM s and rebuild at the other end. The problem is that there are risks in the serialization design in Java, so that too many serialization related vulnerabilities have been exposed.

One reason for the danger of deserialization is that sometimes it is difficult to verify whether the content to be deserialized is at risk, and the incoming data stream can freely reference objects. It is likely that this data stream is malicious code carefully constructed by the attacker.

Therefore, JEP 415 allows you to inform the classes that are allowed or prohibited to be deserialized through a filter configuration during deserialization. If you encounter a prohibited class during deserialization, the deserialization will fail.

14.1. Deserialization example

Suppose that the Poc in the Dog class is a maliciously constructed class, but normal deserialization can succeed.

package com.wdbyte.java17;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * @author niulang
 */
public class JEP415 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Dog dog = new Dog("Siberian Husky");
        dog.setPoc(new Poc());
        // Serialization - object to byte array
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);) {
            objectOutputStream.writeObject(dog);
        }
        byte[] bytes = byteArrayOutputStream.toByteArray();
        // Deserialization - byte array to object
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Object object = objectInputStream.readObject();
        System.out.println(object.toString());
    }
}

class Dog implements Serializable {
    private String name;
    private Poc poc;

    public Dog(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dog{" + "name='" + name + '\'' + '}';
    }
		// get...set...
}

class Poc implements Serializable{

}

Output results:

Dog{name='Siberian Husky'}

14.2. Deserialization filter

In Java 17, you can customize the deserialization filter to intercept classes that are not allowed.

package com.wdbyte.java17;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputFilter;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * @author niulang
 */
public class JEP415 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Dog dog = new Dog("Siberian Husky");
        dog.setPoc(new Poc());
        // Serialization - object to byte array
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);) {
            objectOutputStream.writeObject(dog);
        }
        byte[] bytes = byteArrayOutputStream.toByteArray();
        // Deserialization - byte array to object
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        // Allow com.wdbyte.java17.Dog class, allow all classes in java.base, and reject any other classes
        ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
                        "com.wdbyte.java17.Dog;java.base/*;!*");
        objectInputStream.setObjectInputFilter(filter);
        Object object = objectInputStream.readObject();
        System.out.println(object.toString());
    }
}

class Dog implements Serializable {
    private String name;
    private Poc poc;

    public Dog(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dog{" + "name='" + name + '\'' + '}';
    }
		// get...set...
}

class Poc implements Serializable{
}

In this case, deserialization will get an exception.

Exception in thread "main" java.io.InvalidClassException: filter status: REJECTED
	at java.base/java.io.ObjectInputStream.filterCheck(ObjectInputStream.java:1412)
	at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2053)
	at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1907)
	....

>Extended reading: JEP 415: deserialization filter for the specified context

reference resources

  1. https://openjdk.java.net/projects/jdk/17/
  2. https://docs.oracle.com/en/java/javase/17/

< end >

The article is constantly updated. You can search it through wechat Program ape Alan "Or visit" Program ape Alan blog "Read for the first time. this paper Github.com/niumoo/JavaNotes It has been included. There are many knowledge points and series articles. Welcome Star.

<img width="400px" src=" https://oscimg.oschina.net/oscnet/129650527-af626ed7-fbef-4b46-b332-29155144243a.png "> < / end > < / randomgenerator > < / randomgenerator >

Topics: JDK .NET openjdk