Super detailed introduction to new functions of Java 15

Posted by zavin on Mon, 13 Dec 2021 04:07:59 +0100

Java 15 was released in September 2020. Although it is not a long-term supported version, it also brings 14 new functions, many of which are very practical.

Java 15 official download: https://jdk.java.net/archive/

Java 15 official documentation: https://openjdk.java.net/projects/jdk/15/

New Java 15 features:

JEP

describe

JEP 339

Edwards curve algorithm (EdDSA)

JEP 360

Sealed Classes Preview

JEP 371

Hidden Classes

JEP 372

Remove Nashorn JavaScript engine

JEP 373

Re implement datagram socket APII

JEP 374

Disable and discard Biased Locking

JEP 375

instanceof type matching (second preview)

JEP 377

ZGC: scalable low latency garbage collector (official release)

JEP 378

Text block

JEP 379

Shenandoah: garbage collector with low pause time

JEP 381

Removing Solaris and SPARC ports

JEP 383

External memory access API (second incubator)

JEP 384

Records (second preview)

JEP 385

Discard RMI activation mechanism

JEP339 Edwards curve algorithm (EdDSA)

Java 15 adds a new cryptography algorithm, Edward curve algorithm (EdDSA) signature algorithm. It is developed from Schnorr algorithm and defined and implemented in RFC8032.

package com.wdbyte;

import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.util.Base64;

public class JEP339 {

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519");
        KeyPair kp = kpg.generateKeyPair();
        byte[] msg = "www.wdbyte.com".getBytes(StandardCharsets.UTF_8);
        Signature sig = Signature.getInstance("Ed25519");
        sig.initSign(kp.getPrivate());
        sig.update(msg);
        byte[] s = sig.sign();
        System.out.println(Base64.getEncoder().encodeToString(s));
    }
}

Output results:

VXlpxapU+LSWjVQ0QNJvdpUh6VI6PjSwOQ2pHu65bCfnLR13OyWKunlc9rc+7SMxCh2Mnqf7TmC/iOG8oimbAw==

JEP360: preview of Sealed Classes

As we all know, in Java, if we want to make a class unable to be inherited and modified, we should use the final keyword to modify the class. However, this mechanism of either inheritable or not inheritable is not flexible enough. Sometimes we may want a class to be inherited by some types, but we can't inherit at will. Java 15 tries to solve this problem by introducing the sealed class. The class modified by sealed can specify subclasses. In this way, this class can only be inherited by the specified class.

Moreover, the mechanism of the sealed modified class is transitive. Its subclasses must be modified with the specified keywords, and can only be one of final, sealed and non sealed.

Example: Dog can only be inherited by Collie and TuGou. Use the sealed keyword.

package com.wdbyte;

public  sealed interface Dog permits Collie, TuGou {
    //...
}

Collie can only be inherited by border collie.

package com.wdbyte;

/**
 * Shepherd Dog
 * @author www.wdbyte.com
 */
public sealed class Collie implements Dog permits BorderCollie {

}

Border Collie cannot be inherited. Use the final keyword.

package com.wdbyte;

/**
 *
 * @author www.wdbyte.com
 */
public final class BorderCollie extends Collie{
}

ToGou can be inherited arbitrarily, using the non sealed keyword.

package com.wdbyte;

/**
 * @author niulang
 */
public non-sealed class TuGou implements Dog {
}

JEP371: Hidden Classes

This feature allows developers to introduce a class that cannot be found elsewhere and has a limited class life cycle. This is very beneficial to the use of dynamically generated classes at runtime and can reduce memory consumption. The following is an example.

package com.wdbyte;

public class JEP371Test {
    public static String lookup() {
      return "www.wdbyte.com";
    }
}

Convert the compiled Class of JEP371Test Class to Base64, and then use the new features of Java 15 to load and call the lookup method in the Class.

package com.wdbyte;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Base64;

/**
 * @author www.wdbyte.com
 */
public class JEP371 {

    private static String CLASS_INFO = "yv66vgAAADQAFAoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWCAAIAQAOd3d3LndkYnl0ZS5jb20HAAoBABVjb20vd2RieXRlL0pFUDM3MVRlc3QBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAF0xjb20vd2RieXRlL0pFUDM3MVRlc3Q7AQAGbG9va3VwAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAApTb3VyY2VGaWxlAQAPSkVQMzcxVGVzdC5qYXZhACEACQACAAAAAAACAAEABQAGAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAAAwANAAAADAABAAAABQAOAA8AAAAJABAAEQABAAsAAAAbAAEAAAAAAAMSB7AAAAABAAwAAAAGAAEAAAAEAAEAEgAAAAIAEw==";

    public static void main(String[] args) throws Throwable {
        byte[] classInBytes = Base64.getDecoder().decode(CLASS_INFO);
        Class<?> proxy = MethodHandles.lookup()
            .defineHiddenClass(classInBytes, true, MethodHandles.Lookup.ClassOption.NESTMATE)
            .lookupClass();

        System.out.println(proxy.getName());
        MethodHandle mh = MethodHandles.lookup().findStatic(proxy, "lookup", MethodType.methodType(String.class));
        String result = (String) mh.invokeExact();
        System.out.println(result);
    }
}

Output results:

com.wdbyte.JEP371Test/0x0000000800c01800
www.wdbyte.com

JEP372: removing the Nashorn JavaScript engine

The Nashorn JavaScript engine was introduced in Java 8 and marked obsolete in Java 11. Due to the rapid development of ECMAScript language, the cost of maintaining Nashorn JavaScript is too high and has been completely deleted in Java 15.

Extended reading: Nashorn JavaScript Engine, defer the Nashorn JavaScript Engine

JEP373: re implement datagram socket API

The old Socket API has been re implemented in Java 13. This is also introduced in the introduction of Java 13.

Now, Java 15 re implements the legacy datagram socket.

Extended reading: introduction to new features of Java 13

JEP374: disabling and discarding Biased Locking

Previously, the JVM had a set of lock upgrade mechanisms when handling synchronization operations, such as synchronized synchronization. One of the lock mechanisms is biased lock. However, according to the current Java development environment, there are few opportunities to use these synchronized classes. For example, developers prefer to use HashMap or ArrayList rather than HashTable and Vector.

Even from another angle, the original use of bias lock was to improve performance. Now it seems that the degree of performance improvement and the number of uses are not very useful. The introduction of biased lock increases the complexity of JVM.

Therefore, biased locking is disabled by default and will be completely removed in the near future. For Java 15, we can still use - XX:+UseBiasedLocking to enable biased locking, but it will prompt that this is an deprecated API.

JEP375: instanceof type matching (second preview)

instanceof type matching has been improved in Java 14. This time, it is only previewed again without any changes. It is used to receive more usage feedback. This feature becomes a formal feature in Java 16.

Before, after using instanceof for type judgment, you need to convert the object type before using it.

package com.wdbyte;

import java.util.ArrayList;
import java.util.List;

public class Java14BeaforInstanceof {

    public static void main(String[] args) {
        Object obj = new ArrayList<>();
        if (obj instanceof ArrayList) {
            ArrayList list = (ArrayList)obj;
            list.add("www.wdbyte.com");
        }
        System.out.println(obj);
    }
}

In Java 14, the variable name can be specified for type conversion when judging the type, which is convenient for use.

package com.wdbyte;

import java.util.ArrayList;

public class Java14Instanceof {
    public static void main(String[] args) {
        Object obj = new ArrayList<>();
        if (obj instanceof ArrayList list) {
            list.add("www.wdbyte.com");
        }
        System.out.println(obj);
    }
}

You can see that after using instanceof to judge whether the type is valid, the type will be automatically cast to the specified type.

Output results:

[www.wdbyte.com]

Extended reading: introduction to new features of Java 14

JEP377: ZGC: scalable low latency garbage collector (official release)

ZGC garbage collector was introduced in Java 11, but it was decided to introduce it gradually because of the complexity of the collector. Then constantly listen to the user's feedback and suggestions to fix the problem. Now, we haven't received any feedback from users for a long time. It's time for ZGC to put into formal use. Therefore, when ZGC is officially released in Java 15, the following parameters can be used to enable ZGC.

$ java -XX:+UseZGC className

JEP378: text block

The text block is introduced into the original string text of Java 12 JEP 326. The preview starts in Java 13 JEP 355: text block (Preview), and in Java 14 JEP 368: text block (second preview). Now, in Java 15, text block is a formal functional feature.

String content = """
        {
            "upperSummary": null,\
            "sensitiveTypeList": null,
            "gmtModified": "2011-08-05\s10:50:09",
        }
         """;
System.out.println(content);

Extended reading: introduction to new functions of Java 14 - JEP368 text block

JEP379: Shenandoah: garbage collector with low pause time

The Shenandoah garbage collector was introduced in Java 12 and became a part of the formal function in Java 15. You can enable the Shenandoah garbage collector using the following parameters.

java -XX:+UseShenandoahGC

However, there is no Shenandoah collector in openJDK 15 by default. If you want to use this function, you can download AdoptOpenJDK.

Why is there no Shenandoah garbage collector in openJDK? Shenandoah is a high-performance, low pause time garbage collector, which is a Red Hat led project. When Red Hat first proposed to contribute Shenandoah to OpenJDK, Oracle made it clear that it did not want to support it. As a free software, OpenJDK did not want to support Shenandoah of Red Hat. Finally, Red Hat chose to work with Oracle to design a truly clean pluggable garbage collector interface that allows anyone to easily select a garbage collector for inclusion in their build. Finally, Shenandoah entered JDK 12, but it was not built into OpenJDK.

JEP384: Records (second preview)

The Record class is introduced in Java 14 and enhanced in Java 15. Enables it to support seal types, Record annotations, and related reflection API s.

Example: Record supports sealed type.

package com.wdbyte;

/**
 * @author www.wdbyte.com
 */
public sealed interface DataBase permits DataBaseSelect, DataBaseUpdate {
}

final record DataBaseSelect(@Deprecated String table, String sql) implements DataBase {
}

final record DataBaseUpdate() implements DataBase {
}

In Java Lang. class adds two public methods to obtain Record class information:

  1. RecordComponent[] getRecordComponents()
  2. boolean isRecord()

Other updates

JEP 381: removing Solaris and SPARC ports

Java 14 JEP 362 has abandoned Solaris/SPARC, Solaris/x64 and Linux/SPARC ports, and now it has been officially deleted in Java 15.

JEP 383: external memory access API (second incubator)

JEP 385: abandoned RMI activation mechanism

It just discards RMI activation mechanism and does not affect other functions of RMI.

reference resources

  1. https://openjdk.java.net/projects/jdk/15/
  2. https://docs.oracle.com/en/java/javase/14/docs/specs/rmi/activation.html
  3. https://mkyong.com/java/what-is-new-in-java-15/

---- END ----

Hello world:) that's all for this article. I'm Alan, a front-line technical tool.