Java 15 新特性概述

arcstack约 6439 字大约 21 分钟

Java 15 新特性概述

JDK 15 在 2020 年 9 月 15 号正式发布了!根据发布的规划,这次发布的 JDK 15 将是一个短期的过度版,只会被 Oracle 支持(维护)6 个月,直到明年 3 月的 JDK 16 发布此版本将停止维护。而 Oracle 下一个长期支持版(LTS 版)会在明年的 9 月份候发布(Java 17),LTS 版每 3 年发布一个,上一次长期支持版是 18 年 9 月发布的 JDK 11。@pdai

知识体系

java-15.png
java-15.png

语言特性增强

JEP 378: 文本块(Text Blocks)

文本块,是一个多行字符串,它可以避免使用大多数转义符号,自动以可预测的方式格式化字符串,并让开发人员在需要时可以控制格式。

Text Blocks首次是在JDK 13中以预览功能出现的,然后在JDK 14中又预览了一次,终于在JDK 15中被确定下来,可放心使用了。

    public static void main(String[] args) {
        String query = """
               SELECT * from USER \
               WHERE `id` = 1 \
               ORDER BY `id`, `name`;\
               """;
        System.out.println(query);
    }

运行程序,输出(可以看到展示为一行了):

    SELECT * from USER WHERE `id` = 1 ORDER BY `id`, `name`;

Java14中文本块相关介绍

新功能和库的更新

JEP 339: Edwards-Curve 数字签名算法 (EdDSA)

Edwards-Curve 数字签名算法(EdDSA),一种根据 RFC 8032 规范所描述的 Edwards-Curve 数字签名算法(EdDSA)实现加密签名,实现了一种 RFC 8032 标准化方案,但它不能代替 ECDSA。

与 JDK 中的现有签名方案相比,EdDSA 具有更高的安全性和性能,因此备受关注。它已经在OpenSSL和BoringSSL等加密库中得到支持,在区块链领域用的比较多。

EdDSA是一种现代的椭圆曲线方案,具有JDK中现有签名方案的优点。EdDSA将只在SunEC提供商中实现。

    // example: generate a key pair and sign
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519");
    KeyPair kp = kpg.generateKeyPair();
    // algorithm is pure Ed25519
    Signature sig = Signature.getInstance("Ed25519");
    sig.initSign(kp.getPrivate());
    sig.update(msg);
    byte[] s = sig.sign();

    // example: use KeyFactory to contruct a public key
    KeyFactory kf = KeyFactory.getInstance("EdDSA");
    boolean xOdd = ...
    BigInteger y = ...
    NamedParameterSpec paramSpec = new NamedParameterSpec("Ed25519");
    EdECPublicKeySpec pubSpec = new EdECPublicKeySpec(paramSpec, new EdPoint(xOdd, y));
    PublicKey pubKey = kf.generatePublic(pubSpec);

JEP 371: 隐藏类 Hidden Classes

隐藏类是为框架(frameworks)所设计的,隐藏类不能直接被其他类的字节码使用,只能在运行时生成类并通过反射间接使用它们。

该提案通过启用标准 API 来定义 无法发现 且 具有有限生命周期 的隐藏类,从而提高 JVM 上所有语言的效率。JDK内部和外部的框架将能够动态生成类,而这些类可以定义隐藏类。通常来说基于JVM的很多语言都有动态生成类的机制,这样可以提高语言的灵活性和效率。

  • 隐藏类天生为框架设计的,在运行时生成内部的class。
  • 隐藏类只能通过反射访问,不能直接被其他类的字节码访问。
  • 隐藏类可以独立于其他类加载、卸载,这可以减少框架的内存占用。

Hidden Classes是什么呢

Hidden Classes就是不能直接被其他class的二进制代码使用的class。Hidden Classes主要被一些框架用来生成运行时类,但是这些类不是被用来直接使用的,而是通过反射机制来调用。

比如在JDK8中引入的lambda表达式,JVM并不会在编译的时候将lambda表达式转换成为专门的类,而是在运行时将相应的字节码动态生成相应的类对象。

另外使用动态代理也可以为某些类生成新的动态类。

那么我们希望这些动态生成的类需要具有什么特性呢

  • 不可发现性。 因为我们是为某些静态的类动态生成的动态类,所以我们希望把这个动态生成的类看做是静态类的一部分。所以我们不希望除了该静态类之外的其他机制发现。
  • 访问控制。 我们希望在访问控制静态类的同时,也能控制到动态生成的类。
  • 生命周期。 动态生成类的生命周期一般都比较短,我们并不需要将其保存和静态类的生命周期一致。

API的支持

所以我们需要一些API来定义无法发现的且具有有限生命周期的隐藏类。这将提高所有基于JVM的语言实现的效率。

比如:

    java.lang.reflect.Proxy // 可以定义隐藏类作为实现代理接口的代理类。 
    java.lang.invoke.StringConcatFactory // 可以生成隐藏类来保存常量连接方法; 
    java.lang.invoke.LambdaMetaFactory //可以生成隐藏的nestmate类,以容纳访问封闭变量的lambda主体; 

普通类是通过调用ClassLoader::defineClass创建的,而隐藏类是通过调用Lookup::defineHiddenClass创建的。这使JVM从提供的字节中派生一个隐藏类,链接该隐藏类,并返回提供对隐藏类的反射访问的查找对象。调用程序可以通过返回的查找对象来获取隐藏类的Class对象。

JEP 373: 重新实现 DatagramSocket API

重新实现了老的 DatagramSocket API 接口,更改了 java.net.DatagramSocket 和 java.net.MulticastSocket 为更加简单、现代化的底层实现,更易于维护和调试。

java-15-1.png
java-15-1.png

java.net.datagram.Socketjava.net.MulticastSocket的当前实现可以追溯到JDK 1.0,那时IPv6还在开发中。因此,当前的多播套接字实现尝试调和IPv4和IPv6难以维护的方式。

  • 通过替换 java.net.datagram 的基础实现,重新实现旧版 DatagramSocket API。
  • 更改java.net.DatagramSocketjava.net.MulticastSocket 为更加简单、现代化的底层实现。提高了 JDK 的可维护性和稳定性。
  • 通过将java.net.datagram.Socketjava.net.MulticastSocket API的底层实现替换为更简单、更现代的实现来重新实现遗留的DatagramSocket API。

新的实现

  • 易于调试和维护;
  • 与Project Loom中正在探索的虚拟线程协同。

JVM 优化

JEP 373: ZGC: 可伸缩低延迟垃圾收集器

ZGC是Java 11引入的新的垃圾收集器(JDK9以后默认的垃圾回收器是G1),经过了多个实验阶段,自此终于成为正式特性。ZGC是一个重新设计的并发的垃圾回收器,可以极大的提升GC的性能。支持任意堆大小而保持稳定的低延迟(10ms以内),性能非常可观。目前默认垃圾回收器仍然是 G1,后续很有可以能将ZGC设为默认垃圾回收器。之前需要通过-XX:+UnlockExperimentalVMOptions -XX:+UseZGC来启用ZGC,现在只需要-XX:+UseZGC就可以。

以下是相关介绍:

ZGC 是一个可伸缩的、低延迟的垃圾收集器,主要为了满足如下目标进行设计:

  • GC 停顿时间不超过 10ms
  • 即能处理几百 MB 的小堆,也能处理几个 TB 的大堆
  • 应用吞吐能力不会下降超过 15%(与 G1 回收算法相比)
  • 方便在此基础上引入新的 GC 特性和利用 colord
  • 针以及 Load barriers 优化奠定基础
  • 当前只支持 Linux/x64 位平台 停顿时间在 10ms 以下,10ms 其实是一个很保守的数据,即便是 10ms 这个数据,也是 GC 调优几乎达不到的极值。根据 SPECjbb 2015 的基准测试,128G 的大堆下最大停顿时间才 1.68ms,远低于 10ms,和 G1 算法相比,改进非常明显。
java-11-1.png
java-11-1.png

本图片引用自: The Z Garbage Collector – An Intr