java 8 - java 17 升級指北

福祿網路研發團隊發表於2022-01-11

2014年釋出的java SE 8和2017年釋出的java EE 8,至今還是使用最廣泛的java版本,大部分java開發者對於java 8之後的升級總是敬而遠之,這跟java 9以後的破壞性升級和oracle的商用協議有關,但隨著9月java 17的釋出,我們有更多理由去升級和在新專案中使用更新的java了。

為什麼要升級?

  1. java 9之後的Java改變了更新策略,java 11是8之後的第一個LTS版本,之後每隔半年更新一個小版本,三年更新一個LTS版本,所以java 17是下一個LTS版本。
  2. 最顯著的改善是幾乎免費獲得的效能提升。java 8預設GC是Parallel GC,java 9 之後預設是G1 GC,且就算是同一個GC,新版本中的表現也會比舊版本效能好,我們的程式觸發full GC的次數和GC造成的程式暫停會更短。關於這一點,有一篇文章分析了效能How much faster is Java 17?。除此之外,每一個新的Java版本,尤其是LTS版本,都包含改進,例如解決安全漏洞、改進效能和新增新功能。讓java保持最新有助於專案的健壯性和安全性。開發人員通常也更想在日常工作中使用新技術。
  3. oracleJdk在11版本之後商用是需要付費的,17這個版本又改回了商用免費,openJdk和oracleJdk之間又可以自由選擇了
  4. spring剛剛官宣2022年即將釋出的spring framework 6.0和springboot 3.0版本最低要求java 17,且kafka 3.0版本之後也會棄用java 8,升級已經是一個趨勢,未來更多框架和中介軟體會棄用java 8,作為開發人員也不能停止腳步

升級的注意事項

人們在java 8這個版本不願意升級,除了怕影響專案穩定性,還有就是java 9之後的釋出頻率太快,但在多瞭解一點java 9之後的更新策略後就會知道非LTS版本是不需要升級,也不建議升級的,只有每隔三年釋出的LTS版本才有必要升級(另外java 17之後oracle有個提議改動LTS版本釋出頻率,之後的LTS版本可能每兩年釋出一次);另一方面是有很多破壞性更改,升級後舊專案可能直接報錯。但在java 8釋出至今的7年後,升級的解決方案已經很成熟了,這些問題不應該還是我們升級的阻力

關於升級時可能遇到的問題我做了個彙總,以版本區分,升級時,也建議一步步升級,比如先升級到java11,沒問題再升級到java17,便於發現升級時的問題。以下解決方案基於maven

第一步建議先升級依賴項

如果你的專案基於java 8,在升級前最好先升級依賴項,從java 8升級到java 17是一個很大的跨越,依賴項不升級則出問題的概率會比較高,maven可以用mvn versions:display-dependency-updates命令檢查依賴項更新,輸出會類似這樣

20211116101812

然後可以把依賴項升級到輸出的對應版本,大部分包升級不會出問題,如果有問題,建議去出問題的依賴官方倉庫尋找解決方案。這個命令是直接查詢maven遠端倉庫,如果依賴項多的話會執行比較長的時間

各版本升級需要修改的內容

java 11

java 11刪除了這些原本在jdk中的包:

  1. javaFX
  2. jdk自帶的一些字型,主要影響Apache POI這類依賴字型的庫,解決方法是自行在作業系統安裝字型,比如Ubuntu,需要安裝fontconfig包apt install fontconfig
  3. JMC:Java Mission Control,java自帶的效能分析工具,自java11後從jdk刪除,可自行下載
  4. 刪除java EE和CORBA模組,SE中刪除java EE相關的包是因為這些包已經由java EE提供,而且由於oracle的政策,一些包的名稱空間也改變了,例如JAXB包下的javax.xml.bind.*更改為jakarta.xml.bind.*,下圖列舉了包名的改動,如果專案使用了這些包,需要在程式碼和pom.xml中更改相應包名
    20211115172941

java 14

刪除了CMS GC,對於老專案或針對CMS專門調優過的專案,建議升級後使用G1 GC

java 15

Nashorn JavaScript Engine在這個版本被移除,如果使用了則需要手動新增這個依賴項

<dependency>
    <groupId>org.openjdk.nashorn</groupId>
    <artifactId>nashorn-core</artifactId>
    <version>15.2</version>
</dependency>

java 16

java 16也是一個改動很大的版本,這個版本預設對jdk內部的很多api做了強封裝,預設情況下不可訪問(可以通過選項--illegal-access更改這個行為,但官方不建議),這個主要影響一些工具,比如lombok,而lombok在java 16釋出後不久更新了版本解決這個問題。

如果實在找不到相容的方法,則在pom.xml修改compiler plugin引數可以解決問題:

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-compiler-plugin</artifactId>
 <version>3.8.1</version>
 <configuration>
  <fork>true</fork>
  <compilerArgs>
   <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
   <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
   <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
   <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
   <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
   <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
   <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
   <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
   <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED</arg>
  </compilerArgs>
 </configuration>
</plugin>

如果升級到java 16,但lombok沒有更新,則會報一個讓你一頭霧水的錯誤:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project broken: Compilation failure -> [Help 1]

除此之外沒有更多資訊了,這一點可以說是一個很大的坑

java 17

主要刪除了一些實驗性特性和老舊的API:

  1. applet API被棄用,估計也沒有什麼專案用到這個
  2. 實驗性的AOT和JIT被刪除,最近AOT的特性還是很火的,想使用這個特性的可以使用graalVMspring native是spring基於graalVM的實現,使用spring native的java程式的啟動時間會縮短到毫秒級,但也犧牲了一些執行時優化,可以說是java在雲原生時代的進化,這裡就不過多介紹了。
  3. 還有一個最大的變化是之前的--illegal-access引數不在可用,如果在java 17使用這個引數訪問受限的api則會報出InaccessibleObjectException,大多數情況下只要升級了依賴項是不會碰到這個情況的,但如果出現問題,則可以使用--add-opens來對不可訪問的api授權。

升級完成後可以做的事情

對開發人員來說最想做的自然是使用新的特性,包括var records instanceof switch這些新關鍵字和舊語法的改進,以及Stream和Optional等API的改進等,此處不在贅述。

結語

這裡總結的是一些我自己升級過程中遇到的問題,只要將依賴項同步升級,基本可以解決升級會遇到的所有問題。當然不是所有專案都適合升級的,這裡需要根據專案的情況仔細斟酌,如果是新專案,想跟上技術迭代的腳步,還是非常推薦升級到java 17的。

參考文章及連結:

  1. https://www.optaplanner.org/blog/2021/09/15/HowMuchFasterIsJava17.html
  2. https://www.infoq.com/articles/why-how-upgrade-java17/
  3. https://github.com/johanjanssen/JavaUpgrades
福祿·研發中心 福小文

相關文章