关于java:Java-17-新功能介绍LTS

3次阅读

共计 9575 个字符,预计需要花费 24 分钟才能阅读完成。

点赞 再看,能源有限。Hello world : ) 微信搜「程序猿阿朗」。

本文 Github.com/niumoo/JavaNotes 和 未读代码博客 曾经收录,有很多知识点和系列文章。

Java 17 在 2021 年 9 月 14 日正式公布,Java 17 是一个长期反对(LTS)版本,这次更新共带来 14 个新性能。

OpenJDK Java 17 下载:https://jdk.java.net/archive/

OpenJDK Java 17 文档:https://openjdk.java.net/proj…

<!– more –>

JEP 形容
JEP 306 复原始终严格的浮点语义
JEP 356 加强的伪随机数生成器
JEP 382 应用新的 macOS 渲染库
JEP 391 反对 macOS/AArch64 架构
JEP 398 删除已启用的 Applet API
JEP 403 更强的封装 JDK 外部封装
JEP 406 Switch 模式匹配(预览)
JEP 407 移除 RMI Activation
JEP 409 密封类(Sealed Classes)
JEP 410 JEP 401:移除实验性的 AOT 和 JIT 编译器
JEP 411 弃用 Security Manager
JEP 412 内部函数和内存 API(孵化器)
JEP 414 Vector API(第二孵化器)
JEP 415 指定上下文的反序列化过滤器

此文章属于 Java 新个性教程 系列,会介绍 Java 每个版本的新性能,能够点击浏览。

1. JEP 306:复原始终严格的浮点语义

既然是复原严格的浮点语义,那么阐明在某个工夫点之前,是始终严格的浮点语义的。其实在 Java SE 1.2 之前,所有的浮点计算都是严格的,然而以当初的状况来看,过于严格的浮点计算在当初风行的 x86 架构和 x87 浮点协定处理器上运行,须要大量的额定的指令开销,所以在 Java SE 1.2 开始,须要手动应用关键字 strictfp(strict float point)能力启用严格的浮点计算。

然而在 2021 年的明天,硬件早已发生巨变,当初的问题曾经不存在了,所以从 Java 17 开始,复原了始终严格的浮点语义这一个性。

扩大strictfp 是 Java 中的一个关键字,大多数人可能没有留神过它,它能够用在类、接口或者办法上,被 strictfp 润饰的局部中的 float 和 double 表达式会进行严格浮点计算。

上面是一个示例,其中的 testStrictfp()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:加强的伪随机数生成器

为伪随机数生成器 RPNG(pseudorandom number generator)减少了新的接口类型和实现,让在代码中应用各种 PRNG 算法变得容易许多。

这次减少了 RandomGenerator 接口,为所有的 PRNG 算法提供对立的 API,并且能够获取不同类型的 PRNG 对象流。同时也提供了一个新类 RandomGeneratorFactory 用于结构各种 RandomGenerator 实例,在 RandomGeneratorFactory 中应用 ServiceLoader.provider 来加载各种 PRNG 实现。

上面是一个应用示例:轻易抉择一个 PRNG 算法生成 5 个 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");
        // 应用工夫戳作为随机数种子
        RandomGenerator randomGenerator = l128X256MixRandom.create(System.currentTimeMillis());
        for (int i = 0; i < 5; i++) {System.out.println(randomGenerator.nextInt(10));
        }
    }
}

失去输入:

7
3
4
4
6

你也能够遍历出所有的 PRNG 算法。

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

失去输入:

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

能够看到 Legacy:Random 也在其中,新的 API 兼容了老的 Random 形式,所以你也能够应用新的 API 调用 Random 类生成随机数。

// 应用 Random
RandomGeneratorFactory<RandomGenerator> l128X256MixRandom = RandomGeneratorFactory.of("Random");
// 应用工夫戳作为随机数种子
RandomGenerator randomGenerator = l128X256MixRandom.create(System.currentTimeMillis());
for (int i = 0; i < 5; i++) {System.out.println(randomGenerator.nextInt(10));
}

扩大浏览:加强的伪随机数生成器

3. JEP 382:应用新的 macOS 渲染库

macOS 为了进步图形的渲染性能,在 2018 年 9 月摈弃了之前的 OpenGL 渲染库,而应用了 Apple Metal 进行代替。Java 17 这次更新开始反对 Apple Metal,不过对于 API 没有任何扭转,这一些都是外部批改。

扩大浏览:macOS Mojave 10.14 Release Notes,Apple Metal

4. JEP 391:反对 macOS/AArch64 架构

起因是 Apple 在 2020 年 6 月的 WWDC 演讲中发表,将开启一项长期的将 Macintosh 计算机系列从 x64 适度到 AArch64 的长期打算,因而须要尽快的让 JDK 反对 macOS/AArch64。

Linux 上的 AArch64 反对以及在 Java 16 时曾经反对,能够查看之前的文章理解。

扩大:Java 16 新性能介绍 – JEP 386

5. JEP 398:删除已弃用的 Applet API

Applet 是应用 Java 编写的能够嵌入到 HTML 中的小应用程序,嵌入形式是通过一般的 HTML 标记语法,因为早已过期,简直没有场景在应用了。

示例:嵌入 Hello.class

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

Applet API 在 Java 9 时曾经标记了废除,当初 Java 17 中将彻底删除。

6. JEP 403:更强的 JDK 外部封装

如 Java 16 的 JEP 396 中形容的一样,为了进步 JDK 的安全性,使 --illegal-access 选项的默认模式从容许更改为回绝。通过此更改,JDK 的外部包和 API(要害外部 API 除外)将不再默认关上。

然而在 Java 17 中,除了 sun.misc.Unsafe,应用 --illegal-access 命令也不能关上 JDK 外部的强封装模式了,除了 sun.misc.Unsafe API .

在 Java 17 中应用 --illegal-access 选项将会失去一个命令曾经移除的正告。

➜  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

扩大浏览:JEP 403:更强的 JDK 外部封装,Java 16 新性能介绍

7. JEP 406:switch 的类型匹配(预览)

instanceof 一样,为 switch 也减少了类型匹配主动转换性能。

在之前,应用 instanceof 须要如下操作:

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

多余的类型强制转换,而当初:

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

switch 也能够应用相似的形式了。

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

对于 null 值的判断也有了新的形式。

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

扩大浏览:JEP 406:switch 的类型匹配(预览)

8. JEP 407:移除 RMI Activation

移除了在 JEP 385 中被标记破除的 RMI(Remote Method Invocation)Activation,然而 RMI 其余局部不会受影响。

RMI Activation 在 Java 15 中的 JEP 385 曾经被标记为过期废除,至今没有收到不良反馈,因而决定在 Java 17 中正式移除。

扩大浏览:JEP 407:移除 RMI Activation

9. JEP 409:密封类(Sealed Classes)

Sealed Classes 在 Java 15 中的 JEP 360 中提出,在 Java 16 中的 JEP 397 再次预览,当初 Java 17 中成为正式的性能,相比 Java 16 并没有性能变动,这里不再反复介绍,想理解的能够参考之前文章。

扩大浏览:Java 16 新性能介绍,JEP 409: Sealed Classes

10. JEP 401:移除实验性的 AOT 和 JIT 编译器

在 Java 9 的 JEP 295 中,引入了实验性的提前编译 jaotc 工具,然而这个个性自从引入依赖用途都不太大,而且须要大量的保护工作,所以在 Java 17 中决定删除这个个性。

次要移除了三个 JDK 模块:

  1. jdk.aot – jaotc 工具。
  2. Jdk.internal.vm.compiler – Graal 编译器。
  3. jdk.internal.vm.compiler.management

同时也移除了局部与 AOT 编译相干的 HotSpot 代码:

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

11. JEP 411:弃用 Security Manager

Security Manager 在 JDK 1.0 时就曾经引入,然而它始终都不是爱护服务端以及客户端 Java 代码的次要伎俩,为了 Java 的持续倒退,决定弃用 Security Manager,在不久的将来进行删除。

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

12. JEP 412:内部函数和内存 API(孵化)

新的 API 容许 Java 开发者与 JVM 之外的代码和数据进行交互,通过调用内部函数,能够在不应用 JNI 的状况下调用本地库。

这是一个孵化性能;须要增加 --add-modules jdk.incubator.foreign 来编译和运行 Java 代码。

历史

  • Java 14 JEP 370 引入了内部内存拜访 API(孵化器)。
  • Java 15 JEP 383 引入了内部内存拜访 API(第二孵化器)。
  • Java 16 JEP 389 引入了内部链接器 API(孵化器)。
  • Java 16 JEP 393 引入了内部内存拜访 API(第三孵化器)。
  • Java 17 JEP 412 引入了内部函数和内存 API(孵化器)。

扩大浏览:JEP 412:内部函数和内存 API(孵化)

13. JEP 414:Vector API(二次孵化)

在 Java 16 中引入一个新的 API 来进行向量计算,它能够在运行时牢靠的编译为反对的 CPU 架构,从而实现更优的计算能力。

当初 Java 17 中改良了 Vector API 性能,加强了例如对字符的操作、字节向量与布尔数组之间的互相转换等性能。

14. JEP 415:指定上下文的反序列化过滤器

Java 中的序列化始终都是十分重要的性能,如果没有序列化性能,Java 可能都不会占据开发语言的主导地位,序列化让近程解决变得容易和通明,同时也促成了 Java EE 的胜利。

然而 Java 序列化的问题也很多,它简直会犯下所有的能够设想的谬误,为开发者带来继续的保护工作。然而要阐明的是序列化的概念是没有错的,把对象转换为能够在 JVM 之间自在传输,并且能够在另一端从新构建的能力是齐全正当的想法,问题在于 Java 中的序列化设计存在危险,以至于爆出过很多和序列化相干的破绽。

反序列化危险的一个起因是,有时候咱们不好验证将要进行反序列化的内容是否存在危险,而传入的数据流能够自在援用对象,很有可能这个数据流就是攻击者精心结构的恶意代码。

所以,JEP 415 容许在反序列化时,通过一个过滤配置,来告知本次反序列化容许或者禁止操作的类,反序列化时碰到被禁止的类,则会反序列化失败。

14.1. 反序列化示例

假如 Dog 类中的 Poc 是歹意结构的类,然而失常反序列化是能够胜利的。

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("哈士奇");
        dog.setPoc(new Poc());
        // 序列化 - 对象转字节数组
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);) {objectOutputStream.writeObject(dog);
        }
        byte[] bytes = byteArrayOutputStream.toByteArray();
        // 反序列化 - 字节数组转对象
        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{}

输入后果:

Dog{name='哈士奇'}

14.2. 反序列化过滤器

在 Java 17 中能够自定义反序列化过滤器,拦挡不容许的类。

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("哈士奇");
        dog.setPoc(new Poc());
        // 序列化 - 对象转字节数组
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);) {objectOutputStream.writeObject(dog);
        }
        byte[] bytes = byteArrayOutputStream.toByteArray();
        // 反序列化 - 字节数组转对象
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        // 容许 com.wdbyte.java17.Dog 类,容许 java.base 中的所有类,回绝其余任何类
        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{}

这时反序列化会失去异样。

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)
    ....

扩大浏览:JEP 415:指定上下文的反序列化过滤器

参考

  1. https://openjdk.java.net/proj…
  2. https://docs.oracle.com/en/ja…

< 完 >

文章继续更新,能够微信搜一搜「程序猿阿朗 」或拜访「 程序猿阿朗博客」第一工夫浏览。本文 Github.com/niumoo/JavaNotes 曾经收录,有很多知识点和系列文章,欢送 Star。

正文完
 0