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");});