OpenJDK8升級到OpenJDK11需要注意的修改與異常

目前,JDK兩個長期版本是8和11,由於大部分項目使用的還是8,所以從8升級到11會遇到一些困難。

本篇文章會基於實踐遇到的問題,分類總結可能

1. Java模塊化

從Java 9開始,由於引入了JPMS(https://openjdk.java.net/projects/jigsaw/spec/),開始更精細化的包管理和模塊複用,導致很多JDK默認加載的包被移除了。

其中我們可能會碰到的例如:

  1. sun.reflect.Reflection :參考我的另一篇文章:https://blog.csdn.net/zhxdick/article/details/100710438
  2. EJB的XML工具JAXB相關的類,假設位於com.x.XMLUtils
private static void getXmlFromObject(Book book) throws JAXBException {
    Marshaller marshallerObj = JAXBContext.newInstance(Book.class).createMarshaller();
    marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
 
    StringWriter sw = new StringWriter();
    marshallerObj.marshal(book, sw);
}
  1. sun.misc.BASE64Encoder,假設項目中位於com.x.EncodeUtil:
String encodedString = new BASE64Encoder().encode(inputString.getBytes());

通過JAVA 9 以後自帶的工具jdeps,查看解決方法:

jdeps target\APP.jar
com.x.ReflectionUtils            -> com.sun.crypto.provider               JDK internal API (java.base)
com.x.XMLUtils            -> javax.xml.bind                        java.xml.bind
com.x.EncodeUtil            -> sun.misc                              JDK internal API (JDK removed internal API)
deps --jdk-internals target\pre-jpms.jar
...
JDK Internal API                         Suggested Replacement
----------------                         ---------------------
sun.misc.BASE64Encoder                   Use java.util.Base64 @since 1.8
sun.reflect.Reflection                   Use java.lang.StackWalker @since 9

可以看出,jdeps這個工具,可以找出過期的APi替換方法,也可以找出缺失的模塊。

對於JAXB,通過jdeps命令我們可以知道需要添加java.xml.bind這個模塊,通過添加java啓動參數--add-modules java.xml.bind即可解決。

但是,這樣添加參數,不是長久的辦法,還是添加Maven依賴,比較靠譜:

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>

對於Spring Boot 2.x.x,可以添加依賴:

<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
</dependency>

對於Spring Cloud體系,需要的所有依賴是:

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>${jaxb.version}</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>${jaxb.version}</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>${jaxb.version}</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-xjc</artifactId>
    <version>${jaxb.version}</version>
</dependency>

<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>${activation.version}</version>
</dependency>

2. Lombok編譯異常

報錯:maven編譯報錯:java.lang.ExceptionInInitializerError: com.sun.tools.javac.code.TypeTags

這是因爲Java 9之後的字節碼編譯特性變化,需要升級到1.18.+的版本纔可以。

3. 過時的JVM調優參數以及日誌參數

JDK 8 到JDK 11有很多參數變化,可以總結爲兩類參數的變化,一是GC相關的(GC配置調優更加簡單),二是日誌相關的,日誌統一到了一起,不像之前那麼混亂

具體請參考:

  1. https://docs.oracle.com/en/java/javase/11/tools/java.html#GUID-4856361B-8BFD-4964-AE84-121F5F6CF111
  2. https://docs.oracle.com/javase/9/tools/java.htm#JSWOR-GUID-4856361B-8BFD-4964-AE84-121F5F6CF111
  3. https://docs.oracle.com/javase/10/tools/java.htm#GUID-3B1CE181-CD30-4178-9602-230B800D4FAE__REMOVEDJAVAOPTIONS-A4E6F213

每個說明參考三部分:

  1. Obsolete Java Options: 參數可以被接受但是忽略掉了,但是會有警告,一般這種參數有替代寫法,請用替代的寫法
  2. Deprecated Java Options: 參數可以被接受並有效,但是會有警告,一般這種參數有替代寫法,請用替代的寫法
  3. Removed Java Options: 參數被移除,並且使用的話會有報錯

4. 對於模塊化閉包之後的非法的反射訪問報異常

啓動的時候可能會報如下異常:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$1 (file:/D:/Repositories/maven/org/springframework/spring-core/5.0.13.RELEASE/spring-core-5.0.13.RELEASE.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

建議啓動的時候加上--illegal-access=warn(其他可選的還有"permit" “warn” “debug” “deny”),這裏建議是隻報警(WARN),之後留意升級這些相關的依賴,這樣避免以後JDK升級禁止這種反射,同時保證目前可用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章