文章目录
- 一、JAVA17概述
- 二、语法层面的变化
- 1.密封类
- 2.switch模式匹配(预览)
- 三、API层面变化
- 1.Vector API(第二个孵化器)
- 2.特定于上下文的反序列化过滤器
- 四、其他变化
- 1.恢复始终严格的浮点语义
- 2.JEP 增强型伪随机数生成器
- 3.JEP 382:新的 macOS 渲染管线
- 4.JEP 391:macOS/AArch64 端口
- 5.弃用 Applet API 以进行删除
- 6.强封装 JDK 内部
- 7.JEP 删除 RMI 激活
- 8.删除实验性 AOT 和 JIT 编译器
- 9.弃用安全管理器以进行删除
- 10.外部函数和内存 API(孵化器)
一、JAVA17概述
JDK 16 刚发布半年(2021/03/16),JDK 17 又如期而至(2021/09/14),这个时间点特殊,蹭苹果发布会的热度?记得当年 JDK 15 的发布也是同天
Oracle 宣布,从 JDK 17 开始,后面的 JDK 都全部免费提供!!!
Java 17+ 可以免费使用了,包括商用,更详细的条款可以阅读:
https://www.oracle.com/downloads/licenses/no-fee-license.html
JDK 17 是自 2018 年 JDK 11 后的第二个长期支持版本,支持到 2029 年 9 月,支持时间长达 8 年,这下可以不用死守 JDK 8 了,JDK 17+ 也可以是一种新的选择了。下一个第三个长期支持版本是 JDK 21,时间为 2023 年 9 月,这次长期支持版本发布计划改了,不再是原来的 3 年一次,而是改成了 2 年一次!非长期支持版本还是半年发一次不变,下一个非长期支持版本计划在 2022/03 发布
OpenJDK文档:https://openjdk.java.net/projects/jdk/17/
JDK 17 这个版本提供了 14 个增强功能,另外在性能、稳定性和安全性上面也得到了大量的提升,以及还有一些孵化和预览特性,有了这些新变化,Java 会进一步提高开发人员的生产力。
二、语法层面的变化
1.密封类
密封类,这个特性在 JDK 15 中首次成为预览特性,在 JDK 16 中进行二次预览,在 JDK 17 这个版本中终于正式转正了。
2.switch模式匹配(预览)
使用 switch
表达式和语句的模式匹配以及对模式语言的扩展来增强 Java 编程语言。扩展模式匹配以 switch
允许针对多个模式测试表达式,每个模式都有特定的操作,以便可以简洁安全地表达复杂的面向数据的查询。
instanceof 模式匹配是JAVA14 非常赞的一个新特性! 这次在 JDK 17 中为 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();};
}
直接在 switch 上支持 Object 类型,这就等于同时支持多种类型,使用模式匹配得到具体类型,大大简化了语法量,这个功能还是挺实用的, 目前看转正只是一个时间上的问题而已。
三、API层面变化
1.Vector API(第二个孵化器)
Vector API 旨在通过提供一种在 Java 中编写复杂矢量算法的方法来改善这种情况,使用现有的 HotSpot 自动矢量化器,但使用用户模型使矢量化更加可预测和健壮。手工编码的向量循环可以表达高性能算法,例如向量化 hashCode
或专门的数组比较,自动向量化器可能永远不会优化这些算法。许多领域都可以从这个显式向量 API 中受益,包括机器学习、线性代数、密码学、金融和 JDK 本身的代码。
2.特定于上下文的反序列化过滤器
允许应用程序通过 JVM 范围的过滤器工厂配置特定于上下文和动态选择的反序列化过滤器,该工厂被调用以为每个单独的反序列化操作选择一个过滤器
反序列化不受信任的数据是一种固有的危险活动,因为传入数据流的内容决定了创建的对象、其字段的值以及它们之间的引用。在许多典型用途中,流中的字节是从未知、不受信任或未经身份验证的客户端接收的。通过仔细构建流,攻击者可以导致恶意执行任意类中的代码。如果对象构造具有改变状态或调用其他操作的副作用,那么这些操作可能会损害应用程序对象、库对象甚至 Java 运行时的完整性。禁用反序列化攻击的关键是防止任意类的实例被反序列化,从而防止直接或间接执行它们的方法。
为了保护 JVM 免受反序列化漏洞的影响,应用程序开发人员需要清楚地描述每个组件或库可以序列化或反序列化的对象。对于每个上下文和用例,开发人员应该构建并应用适当的过滤器。例如,如果应用程序使用特定库来反序列化特定对象群组,则可以在调用库时应用相关类的过滤器。创建类的允许列表并拒绝其他所有内容,可以防止流中未知或意外的对象。封装或其他自然应用程序或库分区边界可用于缩小允许或绝对不允许的对象集。
应用程序的开发人员处于了解应用程序组件的结构和操作的最佳位置。此增强功能使应用程序开发人员能够构建过滤器并将其应用于每个反序列化操作。
四、其他变化
1.恢复始终严格的浮点语义
1990 年代后期改变平台默认浮点语义的动力源于原始 Java 语言和 JVM 语义之间的不良交互以及流行的 x86 架构的 x87 浮点协处理器指令集的一些不幸特性. 在所有情况下匹配精确的浮点语义,包括非正规操作数和结果,需要大量额外指令的开销。在没有上溢或下溢的情况下匹配结果可以用更少的开销来实现,这大致是 Java SE 1.2 中引入的修改后的默认浮点语义所允许的。
但是,从 2001 年左右开始在奔腾 4 和更高版本的处理器中提供的 SSE2(流式 SIMD 扩展 2)扩展可以以直接的方式支持严格的 JVM 浮点运算,而不会产生过多的开销。
由于英特尔和 AMD 长期以来都支持 SSE2 和更高版本的扩展,这些扩展允许自然支持严格的浮点语义,因此不再存在具有不同于严格的默认浮点语义的技术动机。
2.JEP 增强型伪随机数生成器
为伪随机数生成器 (PRNG) 提供新的接口类型和实现,包括可跳转的 PRNG 和额外的一类可拆分 PRNG 算法 (LXM)。
- 使在应用程序中交替使用各种 PRNG 算法变得更容易。
- 通过提供 PRNG 对象流更好地支持基于流的编程。
- 消除现有 PRNG 类中的代码重复。
- 小心地保留 class 的现有行为
java.util.Random
。
3.JEP 382:新的 macOS 渲染管线
概括
使用 Apple Metal API 为 macOS 实现 Java 2D 内部渲染管道,作为现有管道的替代方案,现有管道使用已弃用的 Apple OpenGL API。
目标
- 为使用 macOS Metal 框架的 Java 2D API 提供功能齐全的渲染管道。
- 如果 Apple 从未来版本的 macOS 中删除已弃用的 OpenGL API,请做好准备。
- 确保新管道到 Java 应用程序的透明度。
- 确保实现与现有 OpenGL 管道的功能奇偶校验。
- 在选定的实际应用程序和基准测试中提供与 OpenGL 管道一样好或更好的性能。
- 创建适合现有 Java 2D 管道模型的干净架构。
- 与 OpenGL 管道共存,直到它过时。
原因
两个主要因素促使在 macOS 上引入新的基于 Metal 的渲染管道:
- Apple于 2018 年 9 月在 macOS 10.14 中弃用了 OpenGL 渲染库。 macOS 上的Java 2D 完全依赖 OpenGL 进行其内部渲染管道,因此需要新的管道实现。
- Apple 声称Metal 框架(它们替代 OpenGL)具有卓越的性能。对于 Java 2D API,通常是这种情况,但有一些例外。
具体描述
大多数图形 Java 应用程序是使用 Swing UI 工具包编写的,该工具包通过 Java 2D API 呈现。在内部,Java 2D 可以使用软件渲染和屏幕上的 blit,也可以使用特定于平台的 API,例如 Linux 上的 X11/Xrender、Windows 上的 Direct3D 或 macOS 上的 OpenGL。这些特定于平台的 API 通常提供比软件渲染更好的性能,并且通常会减轻 CPU 的负担。Metal 是用于此类渲染的新 macOS 平台 API,取代了已弃用的 OpenGL API。(该名称与 Swing “金属”外观和感觉无关;这只是巧合。)
我们创建了大量新的内部实现代码来使用 Metal 框架,就像我们已经为其他特定于平台的 API 所做的那样。虽然很容易适应现有框架,但新代码在使用图形硬件方面更加现代,使用着色器而不是固定功能管道。这些更改仅限于特定于 macOS 的代码,甚至只更新了 Metal 和 OpenGL 之间共享的最少量代码。我们没有引入任何新的 Java API,也没有改变任何现有的 API。
Metal 管道可以与 OpenGL 管道共存。当图形应用程序启动时,会选择其中一个。目前,OpenGL 仍然是默认设置。仅当在启动时指定或 OpenGL 初始化失败时才使用 Metal,就像在没有 OpenGL 支持的未来版本的 macOS 中一样。
在集成此 JEP 时,Apple 尚未删除 OpenGL。在此之前,应用程序可以通过 -Dsun.java2d.metal=true
在 java
命令行上指定来选择加入 Metal 。我们将在未来的版本中将 Metal 渲染管线设为默认。
在集成到 JDK 之前,我们在Project Lanai 中对这个 JEP 进行了工作。
4.JEP 391:macOS/AArch64 端口
概括
将 JDK 移植到 macOS/AArch64。
原因
Apple 宣布了一项将其 Macintosh 计算机系列从 x64 过渡到 AArch64的长期计划。因此,我们希望看到对 JDK 的 macOS/AArch64 端口的广泛需求。
尽管可以通过 macOS 的内置Rosetta 2 转换器在基于 AArch64 的系统上运行 JDK 的 macOS/x64 版本,但该翻译几乎肯定会带来显着的性能损失。
具体描述
Linux 的 AArch64 端口(JEP 237)已经存在,Windows 的 AArch64 端口(JEP 388)的工作正在进行中。我们希望通过使用条件编译(在 JDK 的端口中很常见)来重用来自这些端口的现有 AArch64 代码,以适应低级约定的差异,例如应用程序二进制接口 (ABI) 和保留的处理器寄存器集。
macOS/AArch64 禁止内存段同时可执行和可写,这一策略称为write-xor-execute (W^X)。HotSpot VM 会定期创建和修改可执行代码,因此此 JEP 将在 HotSpot 中为 macOS/AArch64 实现 W^X 支持。
5.弃用 Applet API 以进行删除
弃用 Applet API 以进行删除。它基本上无关紧要,因为所有 Web 浏览器供应商都已取消对 Java 浏览器插件的支持或宣布了这样做的计划。 Java 9 中的JEP 289先前已弃用 Applet API,但并未将其删除。
弃用或移除标准 Java API 的这些类和接口:
java.applet.Applet
java.applet.AppletStub
java.applet.AppletContext
java.applet.AudioClip
javax.swing.JApplet
java.beans.AppletInitializer
弃用(删除)引用上述类和接口的任何 API 元素,包括以下中的方法和字段:
java.beans.Beans
javax.swing.RepaintManager
javax.naming.Context
6.强封装 JDK 内部
强烈封装 JDK 的所有内部元素,除了 关键的内部 API,如 sun.misc.Unsafe
. 不再可能通过单个命令行选项来放松内部元素的强封装,就像在 JDK 9 到 JDK 16 中那样。
这个 JEP 是JEP 396的继承者,它将 JDK 从默认的宽松强封装转换为默认 强封装,同时允许用户根据需要返回到轻松的姿势。本 JEP 的目标、非目标、动机、风险和假设部分与 JEP 396 的部分基本相同,但为了读者的方便在此处复制。
7.JEP 删除 RMI 激活
RMI 激活机制已过时且已废弃。它已被Java SE 15 中的JEP 385弃用。没有收到针对该弃用的评论。请参阅JEP 385了解完整的背景、原理、风险和替代方案。
Java EE 平台包含一项称为JavaBeans Activation Framework (JAF) 的技术。作为Eclipse EE4J计划的一部分,它后来更名为Jakarta Activation。JavaBeans Activation 和 Jakarta Activation 技术与 RMI Activation 完全无关,它们不受从 Java SE 中删除 RMI Activation 的影响。
java.rmi.activation
从 Java SE API 规范中删除包- 更新RMI 规范以删除提及 RMI 激活
- 去掉实现RMI激活机制的JDK库代码
- 删除 RMI 激活机制的 JDK 回归测试
- 删除 JDK 的
rmid
激活守护进程及其文档
8.删除实验性 AOT 和 JIT 编译器
删除实验性的基于 Java 的提前 (AOT) 和即时 (JIT) 编译器。该编译器自推出以来几乎没有什么用处,维护它所需的工作量很大。保留实验性的 Java 级 JVM 编译器接口 (JVMCI),以便开发人员可以继续使用外部构建的编译器版本进行 JIT 编译。
提前编译(该 jaotc
工具)已通过JEP 295作为实验性功能合并到 JDK 9 中。该 jaotc
工具使用 Graal 编译器,它本身是用 Java 编写的,用于 AOT 编译。
Graal 编译器通过JEP 317在 JDK 10 中作为实验性 JIT 编译器提供。
自从引入这些实验性功能以来,我们几乎没有看到它们的使用,并且维护和增强它们所需的工作量很大。这些特性没有包含在 Oracle 发布的 JDK 16 版本中,并且没有人抱怨。
9.弃用安全管理器以进行删除
弃用安全管理器以在未来版本中移除。安全管理器可追溯到 Java 1.0。多年来,它一直不是保护客户端 Java 代码的主要手段,也很少用于保护服务器端代码。为了推动 Java 向前发展,我们打算弃用安全管理器,以便与旧 Applet API ( JEP 398 )一起删除。
- 为开发人员在 Java 的未来版本中移除安全管理器做好准备。
- 警告用户他们的 Java 应用程序是否依赖于安全管理器。
- 评估是否需要新的 API 或机制来解决使用安全管理器的特定狭窄用例,例如阻塞
System::exit
。
10.外部函数和内存 API(孵化器)
介绍一个 API,Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。通过有效调用外部函数(即 JVM 之外的代码),以及安全地访问外部内存(即不由 JVM 管理的内存),API 使 Java 程序能够调用本地库和处理本地数据,而没有JNI。
- 易用性— 用高级的纯 Java 开发模型替换 Java 本机接口 ( JNI )。
- 性能 — 提供与现有 API(例如 JNI 和
sun.misc.Unsafe
. - 通用性— 提供对不同类型的外部内存(例如,本机内存、持久内存和托管堆内存)进行操作的方法,并随着时间的推移适应其他平台(例如,32 位 x86)和用其他语言编写的外部函数比 C(例如,C++、Fortran)。
- 安全——默认禁用不安全的操作,只有在应用程序开发人员或最终用户明确选择后才允许它们。
Java 平台一直为希望超越 JVM 并与其他平台交互的库和应用程序开发人员提供丰富的基础。Java API 以方便可靠的方式公开非 Java 资源,无论是访问远程数据 (JDBC)、调用 Web 服务(HTTP 客户端)、服务远程客户端(NIO 通道)还是与本地进程通信(Unix 域套接字) . 不幸的是,Java 开发人员在访问一种重要的非 Java 资源时仍然面临重大障碍:与 JVM 位于同一台机器上但在 Java 运行时之外的代码和数据。