Java 17
Java 17 在 2021 年 9 月 14 日正式发布,Java 17 是一个长期支持(LTS)版本,这次更新共带来 14 个新功能。
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);
}
}
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));
}
扩展阅读:增强的伪随机数生成器[15]
JEP 382:使用新的 macOS 渲染库
macOS 为了提高图形的渲染性能,在 2018 年 9 月抛弃了之前的 OpenGL 渲染库 ,而使用了 Apple Metal 进行代替。Java 17 这次更新开始支持 Apple Metal,不过对于 API 没有任何改变,这一些都是内部修改。
扩展阅读:macOS Mojave 10.14 Release Notes[16],Apple Metal[17]
JEP 391:支持 macOS/AArch64 架构
起因是 Apple 在 2020 年 6 月的 WWDC 演讲中宣布,将开启一项长期的将 Macintosh 计算机系列从 x64 过度到 AArch64 的长期计划,因此需要尽快的让 JDK 支持 macOS/AArch64 。
Linux 上的 AArch64 支持以及在 Java 16 时已经支持,可以查看之前的文章了解。
扩展:Java 16 新功能介绍 - JEP 386[18]
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 中将彻底删除。
JEP 403:更强的 JDK 内部封装
如 Java 16 的 JEP 396 中描述的一样,为了提高 JDK 的安全性,使 --illegal-access
选项的默认模式从允许更改为拒绝。通过此更改,JDK 的内部包和 API(关键内部 API[19] 除外)将不再默认打开。
但是在 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 内部封装[20],Java 16 新功能介绍[21]