java17学习笔记
Java17是一个重要的特性发布,也是比较常用的一个版本,根据 2024Java生态统计,Java 17、11 和 8 的用户比例分别为 35%、33% 和 29%。它遵循了自Java10以来引入的Java发布步调,并于2021年 9 月 14 日发布,在Java16发布后的六个月内发布。
306: | Restore Always-Strict Floating-Point Semantics |
356: | Enhanced Pseudo-Random Number Generators |
382: | New macOS Rendering Pipeline |
391: | macOS/AArch64 Port |
398: | Deprecate the Applet API for Removal |
403: | Strongly Encapsulate JDK Internals |
406: | Pattern Matching for switch (Preview) |
407: | Remove RMI Activation |
409: | Sealed Classes |
410: | Remove the Experimental AOT and JIT Compiler |
411: | Deprecate the Security Manager for Removal |
412: | Foreign Function & Memory API (Incubator) |
414: | Vector API (Second Incubator) |
415: | Context-Specific Deserialization Filters |
JEP 306: Restore Always-Strict Floating-Point Semantics
默认使用严格的浮点语义即在类上默认都会加上strictfp修饰词如下图
strictfp是用来避免因硬件或操作系统的差异导致的计算结果不一致。但是即使加了strictfp关键字,计算的精度也不准确,所以精确计算还是要用BigDecimal
JEP 356: Enhanced Pseudo-Random Number Generators
为伪随机数提供新的接口类型和实现(PRNG),包括可跳转的 PRNG 和附加类 可拆分的 PRNG 算法 (LXM)
详情可以查看文章 java17学习笔记-增强型伪随机数生成器-CSDN博客
JEP 382: New macOS Rendering Pipeline
使用 Apple Metal API 作为现有管道的替代方法,为 macOS 实现 Java 2D 内部渲染管道,该管道使用已弃用的 Apple OpenGL 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” Look and Feel 无关,这只是一个巧合。
此次更新创建了大量新的内部实现代码来使用 Metal 框架,就像我们已经为其他特定于平台的 API 所做的那样。虽然很容易适应现有框架,但新代码在使用图形硬件方面更加现代,使用着色器而不是固定的函数管道。这些更改仅限于特定于 macOS 的代码,即使 Metal 和 OpenGL 之间共享的代码也只有极少量被更新。我们没有引入任何新的 Java API,也没有更改任何现有的 API。
Metal 管道可以与 OpenGL 管道共存。当图形应用程序启动时,会选择其中一个。目前,OpenGL 仍然是默认值。仅当在启动时指定 Metal 或 OpenGL 初始化失败时才使用 Metal,就像在不支持 OpenGL 的未来版本的 macOS 中发生的情况一样。
在集成此 JEP 时,Apple 尚未删除 OpenGL。在此之前,应用程序可以通过在命令行上指定来选择加入 Metal。我们将在未来的版本中将 Metal 渲染管线设为默认值。-Dsun.java2d.metal=true
java
JEP 391: macOS/AArch64 Port
将 JDK 移植到 macOS/AArch64。
和windows一样,将 JDK 移植到 Windows/AArch64。windows在java16中已经实现了
JEP 398: Deprecate the Applet API for Removal
弃用 Applet API 以进行删除。这基本上是无关紧要的,因为所有 Web 浏览器供应商要么已经删除了对 Java 浏览器插件的支持,要么宣布了这样做的计划。
弃用标准 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
JEP 403: Strongly Encapsulate JDK Internals
强烈封装JDK的所有内部元素,但关键的内部API(如sun.misc.Unsafe)除外将不再可能像JDK 9到JDK 16,通过单个命令行选项放宽对内部元素的强封装
本JEP的目标、非目标、动机、风险和假设部分与JEP 396基本相同。
可以浏览文章 java17学习笔记-Deprecate the Applet API for Removal-CSDN博客
JEP 406: Pattern Matching for switch (Preview)
继续增强switch表达式后续几个版本都会增强,直到java21版本发布
增强内容可以查看和总结可以查看文章:java17学习笔记-switch总结-CSDN博客
JEP 407: Remove RMI Activation
删除远程方法调用 (RMI) 激活机制,同时保留 RMI 的其余部分。
java15就已经提出 JEP 385: Deprecate RMI Activation for Removal
原因
RMI激活已过时
RMI激活大多未使用
RMI激活会带来持续的维护负担
- 从 Java SE API 规范中删除包
java.rmi.activation
- 更新 RMI 规范以删除提及 RMI 激活
- 删除实现 RMI 激活机制的 JDK 库代码
- 删除 RMI 激活机制的 JDK 回归测试
- 删除 JDK 的激活守护程序及其文档
rmid
JEP 409: Sealed Classes
密封类是java15中提出来新加入的类
详情可以查看文章 java15学习笔记-密封类-CSDN博客
JEP 410: Remove the Experimental AOT and JIT Compiler
删除实验性的基于Java的提前(AOT)和准时(JIT)编译器。自引入以来,这个编译器几乎没有什么用且维护成本巨高。
保留实验性的Java级JVM编译器接口(JVMCI),以便开发人员可以继续使用外部构建的编译器版本进行JIT编译。
JEP 411: Deprecate the Security Manager for Removal
弃用安全管理器,以便在未来的版本中删除。安全管理器可以追溯到Java 1.0。多年来,它一直不是保护客户端Java代码的主要手段,很少用于保护服务器端代码,而且维护成本很高。为了推动Java平台的发展,我们将弃用Security Manager,以便与遗留的Applet API(JEP 398)一起删除。
JEP 412: Foreign Function & Memory API (Incubator)
引入API,Java程序可以通过该API与Java运行时之外的代码和数据进行互操作。通过有效地调用外部函数(即JVM外部的代码),并通过安全地访问外部内存(即不受JVM管理的内存),API使Java程序能够调用本机库并处理本机数据,而不会出现JNI的脆弱性和危险性。
JEP 412: Foreign Function & Memory API (Incubator)
引入一个 API,Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互作。通过有效地调用外部函数(即 JVM 外部的代码)以及安全地访问外部内存(即不受 JVM 管理的内存),API 使 Java 程序能够调用本机库并处理本机数据,而没有 JNI 的脆性和危险性。
详情可以查看文章 Foreign-Memory Access API外部内存API -CSDN博客
JEP 414: Vector API (Second Incubator)
加入矢量,主要用于机器学习、线性代数、密码学、金融和JDK本身的使用。
详情可以查看文章 java16学习笔记-Vector API-CSDN博客
JEP 415: Context-Specific Deserialization Filters
允许应用程序配置特定于上下文和动态选择的 反序列化过滤器通过调用 JVM 范围的过滤器工厂来选择 每个单独反序列化作的筛选器。
import java.io.ObjectInputFilter;
import java.util.function.BinaryOperator;public class FilterInThread implements BinaryOperator<ObjectInputFilter> {// ThreadLocal to hold the serial filter to be appliedprivate final ThreadLocal<ObjectInputFilter> filterThreadLocal = new ThreadLocal<>();// Construct a FilterInThread deserialization filter factory.public FilterInThread() {}/*** The filter factory, which is invoked every time a new ObjectInputStream* is created. If a per-stream filter is already set then it returns a* filter that combines the results of invoking each filter.** @param curr the current filter on the stream* @param next a per stream filter* @return the selected filter*/@Overridepublic ObjectInputFilter apply(ObjectInputFilter curr, ObjectInputFilter next) {if (curr == null) {// Called from the OIS constructor or perhaps OIS.setObjectInputFilter with no current filtervar filter = filterThreadLocal.get();if (filter != null) {// Prepend a filter to assert that all classes have been Allowed or Rejectedfilter = ObjectInputFilter.rejectUndecidedClass(filter);}if (next != null) {// Prepend the next filter to the thread filter, if any// Initially this is the static JVM-wide filter passed from the OIS constructor// Append the filter to reject all UNDECIDED resultsfilter = ObjectInputFilter.merge(next, filter);filter = ObjectInputFilter.rejectUndecidedClass(filter);}return filter;} else {// Called from OIS.setObjectInputFilter with a current filter and a stream-specific filter.// The curr filter already incorporates the thread filter and static JVM-wide filter// and rejection of undecided classes// If there is a stream-specific filter prepend it and a filter to recheck for undecidedif (next != null) {next = ObjectInputFilter.merge(next, curr);next = ObjectInputFilter.rejectUndecidedClass(next);return next;}return curr;}}/*** Apply the filter and invoke the runnable.** @param filter the serial filter to apply to every deserialization in the thread* @param runnable a Runnable to invoke*/public void doWithSerialFilter(ObjectInputFilter filter, Runnable runnable) {var prevFilter = filterThreadLocal.get();try {filterThreadLocal.set(filter);runnable.run();} finally {filterThreadLocal.set(prevFilter);}}
}
var filterInThread = new FilterInThread();ObjectInputFilter.Config.setSerialFilterFactory(filterInThread);// Create a filter to allow example.* classes and reject all othersvar filter = ObjectInputFilter.Config.createFilter("example.*;java.base/*;!*");filterInThread.doWithSerialFilter(filter, () -> {byte[] bytes = new byte[1024];var o = deserializeObject(bytes);System.out.println("111111111111111111111111111111111111111");});