Java 21 官方速覽:全面擁抱虛擬執行緒

程式設計師濟癲發表於2023-12-01

前言

首先,感謝一下不少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和騰訊等公司的開發人員做出的傑出貢獻。

以及來自BellsoftLoongson等小型組織以及獨立開發人員的貢獻,他們總共貢獻了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下載即可。

image

釋出特性

正式釋出的特性,都是未來需要領悟的特性,類似於 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,如果找到類似於ssesse2avx等關鍵詞,說明處理器是支援SIMD指令集的。

所以這個特性在做大規模數學和科學計算時的效率會非常高,可以稍微關注下,估計會繼續孵化。

總結

先總結下,Java 21 正式釋出後,我的感受是,相比於 Java 17 捆綁式的推廣,Java 21 的改進更具有意義。

大家可以重點關注的就是虛擬執行緒、分代ZGC、作用域、結構化併發這幾個,這幾個我覺得比較有意義,可能會改變以後Java的併發程式設計模式。

其他的正式釋出的特性,雖然有必要學習,但我覺得更多是功能性的,類似於 Java 8 的 lambada 表示式和 stream 流,依賴於熟能生巧,而且現在有AI輔助,你不會其實也能寫。

另外,Spring Boot 3.2 最近也釋出了,增加了大量新特性和改進,尤其是對於虛擬執行緒的支援,所以和 Java 21 算是密不可分。

後面我會單獨出一篇文章講述 Spring Boot 3.2 的版本特性。


如果喜歡,請點贊關注↓↓↓,持續分享乾貨文章哦!

相關文章