前言
首先,感謝一下不少xdm私信關心我的身體狀況,我也不是什么厲害的大佬,點開通知看到一堆私信還是蠻感動的。
近來有意大幅縮短了更新頻率,增加了日常調養身體的時間,淋巴結確實變小了,睡眠也逐漸正常,每晚23:30-00:00之間就可以自然入睡,所以精神也好了許多。
上周感冒比較嚴重,這周才好轉,加上一直以來的胃病還沒好,這具身體著實千瘡百孔,令人嘆息,慢慢來吧,xdm在學習之余也要保重自己哦。
本篇主要內容是最近 Java 21 正式發布以后,我對于官方說明的翻譯、整理、排版,以及一點個人注釋加展望,幫助大家節省時間,及時了解下Java的最新動態。
本篇不包含任何案例說明,因為我認為幾年內 Java 21 不會在國內有廣泛應用,所以暫時不需要去學習它,相反,Java 17 的一些新特性可以考慮學習下,我之前的文章里面已經有這樣的專題。
之所以要了解這種重大改進的新版本,目的是為了確定Java未來的趨勢走向,就比如之前lamaba表達式和stream流的出現,基本能確定是一種趨勢,事實證明也確實如此。
正式發布
在今年9月19日Oracle宣布 Java 21 正式發布,JavaSE的產品經理對于這次版本發布做了全面的說明。
首先是對 Java 21 的一個社區貢獻做了說明,在 Java 21 中,標記為已修復的2,585個JIRA問題中,Oracle完成了1,868個問題,而Java社區的其他成員貢獻了717個問題。
可以看出來,Java社區非官方的貢獻度超過官方團隊的三分之一,活躍度依舊是挺高的。
接下來甲骨文著重感謝了一些知名IT公司的研發團隊對于 Java 21 的貢獻和支持,感謝了亞馬遜、ARM、Azul、谷歌、華為、IBM、英特爾、ISCAS、紅帽、Rivos、SAP和騰訊等公司的開發人員
做出的杰出貢獻。
以及來自Bellsoft
和Loongson
等小型組織以及獨立開發人員的貢獻,他們總共貢獻了Java 21 中 8% 的修復。
這里可以看到國內一些比較有名的公司,比如華為、騰訊,但有意思的是,總感覺少了誰……
此外,通過OpenJDK質量推廣計劃,還感謝以下*/開源軟件項目,它們在測試Java 21早期訪問構建時提供了出色的反饋,幫助提高了發布的質量:
- Apache Commons
- Apache ZooKeeper
- AssertJ
- BNYM Code Katas
- JUnit5
- Karate
- MyBatis
這些開源軟件項目里面,我稍微插一句,Zookeeper
出現在里面,說明它對于 Java 21 的大力支持,能被官方點名感謝,可以變相說明它和Java長期的良好合作。
而Zookeeper
在國外其實是很受歡迎的,但在國內因為生態環境的差異,并沒有受到較高的重視,我建議大家可以多學點Zookeeper
,這個中間件非常值得學習。
新增功能
除了數以千計的性能、穩定性和安全性更新之外,Java 21 還提供了數十個新特性和增強
,其中15個增強非常重要
,足以保證它們有自己的JDK增強建議(jep),包括6個預覽特性
和1個孵化特性
。
從這里可以看出,Java 21 是 Java 17 之后另一個非常重要的版本。
接下來,我會把發布特性和預覽孵化特性分開排列,里面有些特性對于大部分研發人員來說其實可以只做了解,但部分重要特性我會著重說明,大家可以重點關注下。
我專門整理了思維導圖,需要的自行在Gitee下載即可。
發布特性
正式發布的特性,都是未來需要領悟的特性,類似于 Java 8 發布之后那些新特性一樣,會逐漸成為Java未來版本的中流砥柱。
1、JEP 440: Record Patterns
通過擴展模式匹配來表達更復雜、可組合的數據查詢
,提高Java編程語言的生產力。
這個特性是在Java19-20都是預覽特性,Java 21 正式發布。
2、JEP 441: switch增強
通過允許在 case 標簽中使用模式,擴展了 switch 表達式
和語句的表達性和適用性。
這個特性在Java17-20都是預覽特性,Java 21 正式發布。
3、JEP 444: 虛擬線程
采用簡單的請求一線程模式編寫的服務器應用程序能夠以接近最佳的硬件利用率進行擴展。
使現有使用java.lang.Thread API的代碼能夠在最小的修改下采用虛擬線程。
使用現有的JDK工具,能夠輕松進行虛擬線程的故障排除、調試和性能分析。
通過引入虛擬線程,加速應用程序開發效率
,尤其適用于云環境中的應用程序,虛擬線程是一種輕量級線程
,極大地減少了編寫、維護和觀察高吞吐量并發應用程序
的工作量。
這個特性在Java19-20都是預覽特性,Java 21 正式發布。
這是 Java 21 版本最重要的一個改進
,也是 Project?Loom 項目一直推進的很重要的一環。
Project?Loom 大家可以了解下,是Java/JVM 生態系統(由 OpenJDK 托管)中的一個較新的項目,它試圖解決傳統并發模型中的限制,目標是顯著減少編寫、維護和觀察高吞吐量并發應用程序的工作量。
說白了,就是Oracle為了改進Java高并發難題推進的一個新項目。
虛擬線程直白點講,就是其他編程語言中已經出現過的協程,也是Java一直被詬病的一點,這次終于在正式版本發布出來了,我覺得值得鼓勵,是個好勢頭。
我期望Java把其他編程語言的優點都抄過來,像什么Python、C#、Go,都抄過來,使勁抄,用力抄,我舉雙手雙腳歡迎。
4、JEP 431: 有序集合
引入新的接口,用于表示按照定義好的遇見順序進行排列的集合。每個這樣的集合都有一個明確定義的第一個元素、第二個元素,依此類推,直到最后一個元素。
為訪問其第一個和最后一個元素提供統一的API,并為按相反順序處理其元素提供統一的API。
通過提供一組統一的操作,它們適用于表示具有定義好順序的元素序列的集合類型,提高開發者的生產力。
在Java中,集合是非常常用的工具,這個有序集合算是對于集合工具的加強,是否實用現在還不好說,畢竟現有的工具也足以解決絕大部分問題。
5、JEP 439: 分代ZGC
通過擴展 Z Garbage Collector (ZGC) 來維護年輕對象和老年對象的不同分代,提高應用程序的性能。
使用 Generational ZGC 運行的應用程序應該享有以下好處:
- 較低的分配停頓風險。
- 較低的堆內存開銷要求。
- 較低的垃圾回收 CPU 開銷。
相比非分代 ZGC,這些好處應該不會顯著降低吞吐量。同時,非分代 ZGC 的關鍵特性應該得以保留:
- 暫停時間不應超過 1 毫秒。
- 支持從幾百兆字節到數太字節的堆大小。
- 最低限度的手動配置需求。
這是另一個非常重要的改進
,主要為了減少垃圾回收對應用程序的停頓時間,是一種低延遲的垃圾回收器
。
ZGC實現了許多創新的技術,例如并發的垃圾回收、分代堆布局、柔性內存操作等,可以說非常適用于需要低延遲和高吞吐量的應用
。
但并不是有了ZGC,你什么應用都用ZGC,在一些特定情況下它也可能會對應用程序的吞吐量產生一些小幅度的影響,所以要根據具體應用場景的需求進行評估和選擇。
這個改進大家現在只需了解,但以后要花時間研究,對于大部分Java程序員而言,你可能不會真正接觸到它,但是你避不開JVM相關的面試題啊……這東西可以預見未來會是Java面試題中的主角之一。
6、JEP 452: 密鑰封裝機制API
引入密鑰封裝機制(KEM)的API,KEM是一種使用公鑰加密的加密技術
,用于保護對稱密鑰的安全性
。
使應用程序能夠使用KEM算法,例如RSA Key Encapsulation Mechanism (RSA-KEM),橢圓曲線綜合加密方案 (ECIES),以及國家標準與技術研究所(NIST)后量子密碼標準化過程中的候選KEM算法。
使KEM在更高級的協議,如傳輸層安全 (TLS),以及混合公鑰加密 (HPKE, RFC 9180)等密碼方案中使用。
允許安全提供者在Java代碼或本地代碼中實現KEM算法。
包括在RFC 9180的§4.1中定義的Diffie-Hellman KEM (DHKEM)的實現。
7、JEP 449: 棄用并刪除32位x86端口
棄用Windows 32位x86(x86-32)端口,并計劃在未來的發布版本中刪除它
。
更新構建系統,在嘗試為Windows 32位x86(x86-32)配置構建時發出錯誤信息。可以通過一個新的配置選項來抑制錯誤信息。
在相關文檔中標記該端口和相關的端口特定功能為棄用,以便將來刪除。
這個是可以預見的,因為這個平臺的使用率已經下降很多了,對于未來Java的發展和創新是一種阻礙,同樣也是為了更好的支持虛擬線程,所以棄用完全說得通。
8、JEP 451: 準備禁止動態加載代理
當代理以動態方式加載到運行的JVM中時,發出警告。這些警告旨在為將來的發布版本做準備,該版本默認情況下禁止動態加載代理,以提高默認的完整性。在任何發布版本中,啟動時加載代理的可操作性工具不會導致發出警告。
為將來的JDK發布版本做準備,默認情況下禁止在正在運行的JVM中加載代理。
重新評估可操作性(Serviceability)與完整性之間的平衡,可操作性涉及對運行中的代碼進行臨時更改,而完整性假定運行中的代碼不會隨意更改。
確保大多數工具——不需要動態加載代理的工具——不受影響。
將動態加載代理的能力與其他所謂的“超級”功能(如深層反射)保持一致。
這個需要大家關注一下,我認為主要目的是因為安全性,Java一向對于安全性是有較高要求的,動態代理本身存在潛在的安全風險。
Java 21 這里說的目前只是會發出警告,但是也暗示了給未來的版本做準備,沒說是什么準備,搞不好有可能會棄用了。
預覽孵化特性
預覽和孵化的特性只需要選擇性了解
就行,因為有些預覽版本不一定最終會正式發布,是有待商榷的,最終根據社區的反饋才能決定是否正式啟用。
1、JEP 430: 字符串模板
通過簡化
包含運行時計算值的字符串的表達
,簡化了Java程序的編寫
,增強Java編程語言的可讀性、可寫性和可維護性。
這個我覺得最終會正式發布的,參考了其他編程語言的優點,對于一向被詬病寫法較重的Java來說,也是喜人的改變,如果一直以這種勢頭前進,依然值得大家擁抱這門語言。
2、JEP 443: 未命名的模式和變量
通過引入未命名模式,對Java語言進行增強,未命名模式可以匹配記錄組件,而無需指定組件的名稱或類型;
引入未命名變量,這些變量可以進行初始化但不會被使用。這兩者都以下劃線字符 _ 表示
。
通過省略不必要的嵌套模式,提高記錄模式的可讀性;
通過確定必須聲明但將不會被使用的變量(例如在catch子句中),提高所有代碼的可維護性。
這個和上一個類似,也是增強Java的實用性,比較典型的應用就是try..catch、for循環、switch等等,都可以用到。
3、JEP 445: 未命名類和實例主方法
通過減少樣板代碼和儀式感,使學生能夠編寫他們的第一個程序,而無需理解為大型程序設計的語言特性。
這個純粹是降低入門門檻了,感覺有一丁點Python那味兒了。
4、JEP 446: 作用域值
在線程內部和跨線程之間實現不可變數據的共享。
- 易用性 - 提供了一種編程模型,可以在線程內部和子線程之間共享數據,以簡化對數據流的推理。
- 可理解性 - 從代碼的語法結構中明確共享數據的生命周期。
- 健壯性 - 確保只有合法的調用方可以訪問調用方共享的數據。
- 性能 - 將共享數據視為不可變的,以便允許大量線程的共享,并實現運行時優化。
在Java20中經歷了一次孵化
這個特性值得關注,不僅能避免數據泄露或竄改,還可以在線程之間共享,相當于減少了復制,提高了性能。
5、JEP 453: 結構化并發
通過引入結構化并發的API,簡化并發編程
。
提倡一種并發編程風格,可以消除由取消和關閉引起的常見風險,如線程泄漏和取消延遲。
改進并發代碼的可觀察性。
通過引入結構化并發的API,簡化并發編程
。它簡化了錯誤處理和取消操作,提高了可靠性,并增強了可觀察性。
在Java19-20中經歷了兩次孵化
這個雖然在孵化,但我不得不說,是Java正在極力解決高并發編程難題的明顯跡象之一,前面的虛擬線程、作用域和這個特性都是相輔相成,已經充分說明Java正在 Java 8 的版本之后,再次決定對于并發編程做一次進化。
CompleTableFuture雖然已經很不錯了,但只是對舊版本任務編排的優化,并沒有解決Java本身并發編程的難題,所以在生產環境應用起來依然容易造成人為缺陷。
至少我使用時是慎之又慎的,一定要分析清楚場景和評估可能的風險,才會決定在某個功能上使用。
但有了虛擬線程之后,加上作用域、結構化并發,我認為是一種進化吧,雖然這些已經不是創新了,但期待值很高。
還有一點需要考量,Java本身迭代到目前這個版本,我認為有些地方不是那么容易更改的,這次能優化到什么程度,是不是真的好用,我還是保留懷疑態度。
6、JEP 442: 外部函數和內存 API
引入一個API,使Java程序能夠與Java運行時之外的代碼和數據進行交互
。
通過有效地調用外部函數(即JVM之外的代碼)和安全地訪問外部內存(即JVM不管理的內存),該API使Java程序能夠調用本地庫和處理本地數據,而不會出現JNI的脆弱性和危險性。
- 易用性 - 用優秀的純Java開發模型替代了Java Native Interface (JNI)。
- 性能 - 提供與JNI和sun.misc.Unsafe等現有API相當甚至更好的性能。
- 通用性 - 提供操作不同類型的外部內存的方法(例如本地內存、持久內存和托管堆內存),以及隨著時間的推移適應其他平臺(例如32位x86)和其他語言編寫的外部函數(例如C++、Fortran)。
- 安全性 - 允許程序對外部內存執行不安全的操作,但默認情況下提醒用戶此類操作存在風險。
在Java19-20中經歷了兩次預覽
這個就是用來替代JNI的,JNI什么尿性不用多說了吧,臭名昭著了。
7、JEP 448: 向量API
引入一個API,用于表達向量計算,在支持的CPU架構上可靠地在運行時編譯為最佳向量指令,從而實現比等效的標量計算更高的性能。
以下是一些顯著的改變:
- 向向量掩碼中添加了異或(xor)操作。
- 改進了向量洗牌的性能,特別是在重新排列向量元素和在向量之間進行轉換時。
提供一個清晰簡潔的API,能夠清晰簡潔地表達由向量操作組成的各種向量計算,這些向量計算由循環內的序列組成,并可能帶有控制流程。
該API應該與特定的CPU架構無關,能夠在支持向量指令的多個架構上實現。
提供在x64和AArch64架構上可靠的運行時編譯和性能。
與Valhalla項目保持一致。
在Java16-20中經歷了五次孵化
這個還是實驗性質的,未來會不會應用尚不好說,畢竟已經經歷了五次孵化了。
如果讀不懂這個特性,我可以舉個很簡單的例子,比如你要給一個數組每個元素都+1,首先想到的就是用for循環遍歷,對每個元素進行計算操作。那么現在有了向量API,你可以一次對多個元素一起計算,從串行變成并行,效率是不是就提高了。
但需要在具備SIMD(單指令多數據流)能力的機器上,現在Windows一般都是支持的,Linux的話一般也支持,且可以用命令查看:
cat /proc/cpuinfo
,如果找到類似于sse
,?sse2
,?avx
等關鍵詞,說明處理器是支持SIMD指令集的。所以這個特性在做大規模數學和科學計算時的效率會非常高,可以稍微關注下,估計會繼續孵化。
總結
先總結下,Java 21 正式發布后,我的感受是,相比于 Java 17 捆綁式的推廣,Java 21 的改進更具有意義。
大家可以重點關注的就是虛擬線程、分代ZGC、作用域、結構化并發
這幾個,這幾個我覺得比較有意義,可能會改變以后Java的并發編程模式。
其他的正式發布的特性,雖然有必要學習,但我覺得更多是功能性的,類似于 Java 8 的 lambada 表達式和 stream 流,依賴于熟能生巧,而且現在有AI輔助,你不會其實也能寫。
另外,Spring Boot 3.2
最近也發布了,增加了大量新特性和改進,尤其是對于虛擬線程的支持,所以和 Java 21 算是密不可分。
后面我會單獨出一篇文章講述 Spring Boot 3.2
的版本特性。
如果喜歡,請點贊關注↓↓↓,持續分享干貨文章哦!