升級到Java 17沒這麼簡單

mokeyWie發表於2021-11-23

前言

最近在給公司新架構做技術選型,剛好 Java 17 也正式釋出一段日子了,而且是LTS長期支援版本,就想著直接用起來吧,裡面有些特性還是非常好用的,比如:

遇到的問題

其中最主要的原因就是 Java 模組化之後,有些 jdk 內部的類不能被訪問了,但是在 Java 16 之前都只是警告,而在 Java 16 之後則會直接報錯,目前依賴了cglibjavassist的框架可能都會因此導致專案無法啟動,丟擲如下異常:

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,歡迎掃碼??關注!不定期在公眾號中分享JAVAGolang前端dockerk8s等乾貨知識。

wechat

相關文章