OpenJDK8升级到OpenJDK11需要注意的修改与异常

简介: 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升级禁止这种反射,同时保证目前可用。



相关文章
|
12月前
|
XML 前端开发 JavaScript
JDK8升级JDK17过程中遇到的那些坑
JDK8虽然非常好,但是JDK版本已经发布到JDK20了,且JDK8后的版本升级了很多新的特性,如模块化、ZGC以虚拟线程、结构性并发等,也是非常有吸引力的,所以决定将基于JDK8的项目升级到最近的LTS版本JDK17。
1366 0
|
C++
编译OpenJDK11,必须使用VS 2017
编译OpenJDK11,必须使用VS 2017
64 0
编译OpenJDK11,必须使用VS 2017
|
Java
VS2015编译的OpenJDK8,会崩溃
VS2015编译的OpenJDK8,会崩溃
66 0
|
Java Windows
使用VS2015编译OpenJDK8
使用VS2015编译OpenJDK8
90 0
|
Java
OPENJDK8 32位版本,JAVA启动时Xmx参数的影响
OPENJDK8 32位版本,JAVA启动时Xmx参数的影响
142 0
OpenJDK8和OpenJDK8u的差异
OpenJDK8和OpenJDK8u的差异
283 0
|
Java
编译OpenJDK8:OpenJDK8与OpenJDK8u运行结果相差很大
编译OpenJDK8:OpenJDK8与OpenJDK8u运行结果相差很大
150 0
编译OpenJDK12:可以用VS2010到VS2017
编译OpenJDK12:可以用VS2010到VS2017
54 0
|
监控 Java Spring
从OpenJDK8到OpenJDK11 - StackWalker类
从OpenJDK8到OpenJDK11 - StackWalker类
Java 升级JDK版本常见的问题解决方案
Java 升级JDK版本常见的问题解决方案
Java 升级JDK版本常见的问题解决方案