升級到Java 17沒這麼簡單
前言
最近在給公司新架構做技術選型,剛好 Java 17 也正式發佈一段日子了,而且是 LTS
長期支持版本,就想着直接用起來吧,裏面有些特性還是非常好用的,比如:
- JEP 378:文本塊支持
- JEP 395:Record 類型
- JEP 286:變量類型推導
- More...
遇到的問題
其中最主要的原因就是 Java 模塊化之後,有些 jdk 內部的類不能被訪問了,但是在 Java 16 之前都只是警吿,而在 Java 16 之後則會直接報錯,目前依賴了 cglib
和 javassist
的框架可能都會因此導致項目無法啟動,拋出如下異常:
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @39aeed2f at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:357) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199) at java.base/java.lang.reflect.Method.setAccessible(Method.java:193) at net.sf.cglib.core.ReflectUtils$1.run(ReflectUtils.java:61) at java.base/java.security.AccessController.doPrivileged(AccessController.java:554) at net.sf.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:52) at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:243) at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:332)
從 Java 16 開始,JEP 396會默認把 --illegal-access
參數設置為 deny
,即默認禁用訪問封裝的包以及反射其他模塊,這樣就會導致上面的異常,在此之前該參數默認值一直都是 --illegal-access=permit
,只會產生警吿,而不會報錯,所以如果是 Java 16 的話需要在執行 Java 程序時把 --illegal-access
設置為 permit
,這樣就可以解決問題,示例:
java -jar --illegal-access=permit app.jar
從 Java 17 開始就更狠了,JEP 403直接把 --illegal-access
參數移除了,如果需要啟用訪問封裝的包,需要在執行 Java 程序時加上 --add-opens java.base/java.lang=ALL-UNNAMED
選型,示例:
java -jar --add-opens java.base/java.lang=ALL-UNNAMED app.jar
如果是在 IDEA 中運行需要配置對應的 VM 參數,示例:
雖然説加完參數之後是可以跑起來,但是我認為這是一個破壞性的改動,因為這樣的話,如果有一天 Java 版本變化了,參數又失效了,那麼所有的項目都需要更新,這樣會導致項目的維護成本大大增加,所以這裏不建議使用。
開源框架升級進度跟蹤
那麼有沒有辦法不加啟動參數就能正常運行呢,答案是肯定的,只不過需要等開源框架全換算 Java 17 的新 API,目前我跟蹤到的兩個項目都還沒有適配 Java 17。
Spring
SpringBoot 2.5.0 開始支持 Java 17,沒啥問題。
apollo 配置中心
apollo 目前的 master 分支代碼是已經適配好了,但是還沒有正式發版,比較奇怪的事是, apollo 之前升級了底層依賴包來適配 Java 17,但是後來又回滾回來了,不知道是出於什麼原因。
dubbo
dubbo 有個issue 7593四月份就提出來了,但是一直沒人跟進。
總結
一頓操作下來發現不行,最終還是先換成了 Java 15,待時機成熟的時候再升級到 Java 17。
我是 MonkeyWie ,歡迎掃碼:point_down::point_down:關注!不定期在公眾號中分享 JAVA
、 Golang
、 前端
、 docker
、 k8s
等乾貨知識。
- BFE開源項目2021年回顧和致謝
- 三大核心能力,揭示全面釋放數據價值的獨門祕訣
- 技術升級!國內公有云廠商首個支持保留消息功能
- 巧用 CSS 實現動態線條 Loading 動畫
- CTF&爬蟲:掌握這些特徵,一秒識別密文加密方式
- 一鍵AI着色,黑白老照片畫面瞬間鮮活
- 可觀測領域準獨角獸「駐雲科技」完成2億元新一輪融資
- 【微信小程序雲開發】1分鐘學會實現上傳、下載、預覽、刪除圖片,並且以九宮格展示圖片
- 強強聯袂!騰訊雲TDSQL與國雙戰略簽約,錨定國產數據庫巨大市場
- 如何優雅地讀寫HttpServletRequest和HttpServletResponse的請求體
- 優艾智合完成B系列超3億元人民幣融資 加速移動機器人規模化落地
- 5個很少被提到但能提高NLP工作效率的Python庫
- 徹底理解Golang Slice
- 全新的 Vue3 狀態管理工具:Pinia
- 想給用户天涯若比鄰的體驗?業務全球化面臨的三重挑戰
- 設計模式【4】-- 建造者模式詳解
- 分佈式鎖及其實現
- TDSQL | 國產化浪潮下,數據庫 雲如何跑上核心業務?
- 為了生成唯一id,React18專門引入了新Hook:useId
- Java SPI機制從原理到實戰