从JDK11升级至JDK17迁移笔记

|15707字|1132阅读

1.本地保留多个JDK版本

        选择在JDK11的安装父目录下创建一个JDK17文件夹,用于存放从Oracle官网下载的JDK17压缩包,解压后放置到此文件夹下。也可以使用IDEA2021.2.2及以上版本下载JDK17版本至此目录,具体的JDK供应商可自行选择。


2.修改Maven及IDEA项目结构中涉及到JDK版本的配置信息

主要有五个地方需要检查及修改:

  • 1.pom.xml文件中的配置项java.version、maven.compiler.source、maven.compiler.target需要调整为17;
  • 2.IDEA中SDK版本需要修改为17(使用的JDK版本路径需要配置为JDK17,对应上面JDK版本);
  • 3.IDEA中Project Structure中的SDKs中添加JDK17,并选择JDK17;
  • 4.Project Settings中Modules中每个子模块的Language Level需要调整为17,Dependencies中Modules SDK选择JDK17,并在刷新后的.idea/compiler.xml项目配置文件中检查是否都已改为target="17";
  • 5.Project Settings中Project选项卡中 Project SDK、Project language level需要都调整为JDK17。

上述检查完成后需要修改完保存然后重新编译。


3.编译打包遇到Lombok异常抛出,打包构建失败

查询Github相关issue得知,需要升级lombok版本至1.8.20及更高版本可解决遇到的问题。


4.编译打包遇到Dubbo compiler打包出现异常抛出影响构建

可参考如下配置,在maven-compiler-plugin插件的configuration节点下增加compilerVersion、executable两条配置项,并保证JDK版本一致都为17。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.compiler.release>17</maven.compiler.release>
        <file_encoding>UTF-8</file_encoding>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven-compiler-plugin.version}</version>
        <configuration>
            <compilerArgument>-proc:none</compilerArgument>
            <fork>true</fork>
            <compilerVersion>${java.version}</compilerVersion>
            <source>${maven.compiler.source}</source>
            <target>${maven.compiler.target}</target>
            <encoding>${file_encoding}</encoding>
            <executable>D:\ProgramFiles\Java\JDK\JDK17\bin\javac.exe</executable>
        </configuration>
    </plugin>

后续经过多次测试发现是由于项目中引入Google Guava库的方式存在问题引起的,编译期间需要依赖Guava中的两个类,但未获取到导致编译失败过不去,问题修复后,该包可以正常构建完成。


5.打包成功后Dubbo框架使用Zookeeper作为注册中心启动失败无法连接ZK注册中心

升级Dubbo对应依赖的Zookeeper及相关依赖Jar版本,未找到定义的Class(未引入必要的JAR包)。

具体修改可参考如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
        <!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-dependencies-zookeeper -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper</artifactId>
            <version>${dubbo.version}</version>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.curator</groupId>
                    <artifactId>curator-framework</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.curator</groupId>
                    <artifactId>curator-recipes</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.7.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>5.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>5.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.codahale.metrics</groupId>
            <artifactId>metrics-core</artifactId>
            <version>3.0.2</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>9.4.43.v20210629</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>9.4.43.v20210629</version>
        </dependency>


6.JDK9及以上版本中存在的启动抛出InaccessibleObjectException异常

异常堆栈信息大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dubboBootstrapApplicationListener': Initialization of bean failed; nested exception is java.lang.IllegalStateException: Failed to create adaptive instance: java.lang.IllegalStateException: Can't create adaptive extension interface org.apache.dubbo.metadata.report.MetadataReportFactory, cause: 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 @5c5eefef
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:610)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213)
	at org.springframework.context.event.AbstractApplicationEventMulticaster.retrieveApplicationListeners(AbstractApplicationEventMulticaster.java:264)
	at org.springframework.context.event.AbstractApplicationEventMulticaster.getApplicationListeners(AbstractApplicationEventMulticaster.java:221)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
	at org.springframework.context.support.AbstractApplicationContext.registerListeners(AbstractApplicationContext.java:881)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:580)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332)
	at com.acanx.meta.subscriber.MetaSubscriberApplication.main(MetaSubscriberApplication.java:17)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.IllegalStateException: Failed to create adaptive instance: java.lang.IllegalStateException: Can't create adaptive extension interface org.apache.dubbo.metadata.report.MetadataReportFactory, cause: 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 @5c5eefef
	at org.apache.dubbo.common.extension.ExtensionLoader.getAdaptiveExtension(ExtensionLoader.java:658)
	at org.apache.dubbo.metadata.report.MetadataReportInstance.init(MetadataReportInstance.java:47)
	at org.apache.dubbo.config.bootstrap.DubboBootstrap.startMetadataCenter(DubboBootstrap.java:776)
	at org.apache.dubbo.config.bootstrap.DubboBootstrap.initialize(DubboBootstrap.java:569)
	at org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener.initDubboConfigBeans(DubboBootstrapApplicationListener.java:92)
	at org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener.checkCallStackAndInit(DubboBootstrapApplicationListener.java:161)
	at org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener.setApplicationContext(DubboBootstrapApplicationListener.java:145)
	at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:128)
	at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:102)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:422)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
	... 23 common frames omitted
Caused by: java.lang.IllegalStateException: Can't create adaptive extension interface org.apache.dubbo.metadata.report.MetadataReportFactory, cause: 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 @5c5eefef
	at org.apache.dubbo.common.extension.ExtensionLoader.createAdaptiveExtension(ExtensionLoader.java:1091)
	at org.apache.dubbo.common.extension.ExtensionLoader.getAdaptiveExtension(ExtensionLoader.java:654)
	... 34 common frames omitted
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 @5c5eefef
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
	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 javassist.util.proxy.SecurityActions.setAccessible(SecurityActions.java:159)
	at javassist.util.proxy.DefineClassHelper$JavaOther.defineClass(DefineClassHelper.java:213)
	at javassist.util.proxy.DefineClassHelper$Java11.defineClass(DefineClassHelper.java:52)
	at javassist.util.proxy.DefineClassHelper.toClass(DefineClassHelper.java:260)
	at javassist.ClassPool.toClass(ClassPool.java:1240)
	at javassist.CtClass.toClass(CtClass.java:1392)
	at org.apache.dubbo.common.compiler.support.JavassistCompiler.doCompile(JavassistCompiler.java:82)
	at org.apache.dubbo.common.compiler.support.AbstractCompiler.compile(AbstractCompiler.java:58)
	at org.apache.dubbo.common.compiler.support.AdaptiveCompiler.compile(AdaptiveCompiler.java:45)
	at org.apache.dubbo.common.extension.ExtensionLoader.createAdaptiveExtensionClass(ExtensionLoader.java:1114)
	at org.apache.dubbo.common.extension.ExtensionLoader.getAdaptiveExtensionClass(ExtensionLoader.java:1100)
	at org.apache.dubbo.common.extension.ExtensionLoader.createAdaptiveExtension(ExtensionLoader.java:1089)
	... 35 common frames omitted

当前解决办法是在IDEA的启动配置中的Enviroment中指定VM Options参数,添加JVM启动参数:

1
--add-opens java.base/java.lang=ALL-UNNAMED


7.生产环境升级JDK

        生产环境JDK17升级安装及配置操作流程具体如下:

7.1、查看linux系统信息,并升级系统

1
2
3
4
5
6
$ cat /etc/os-release       
$ lsb_release -a
$ uname -a
$ sudo apt update
$ sudo apt list --upgradable
$ sudo apt upgrade -y


7.2、下载JDK17

在Linux系统下,linux 系统下,使用wget下载

1
$ wget https://download.oracle.com/java/17/archive/jdk-17.0.1_linux-x64_bin.tar.gz


7.3、解压jdk-17_linux-x64_bin.tar.gz

1
tar -zxvf jdk-17.0.1_linux-x64_bin.tar.gz 


7.4、复制到/usr/local/JDK17

1
2
3
4
5
# 在/usr/local/目录下执行以下命令复制JDK二进制文件至/usr/local/JDK17目录
#; mkdir JDK17     //  创建文件夹
#; rm -rf JDK17    // 删除文件夹

$ mv jdk-17.0.1 JDK17


7.5、配置环境变量

1
2
3
4
5
6
$ sudo vim /etc/profile
-----------------------------------------------------
export JAVA_HOME=/usr/local/JDK11
export CLASSPATH=.:$JAVA_HOME/lib
export PATH=.:$JAVA_HOME/bin:$JAVA_HOME/lib:$PATH
-----------------------------------------------------

调整JDK的JAVA_HOME配置,更新为升级至JDK17后的路径

1
2
3
export JAVA_HOME=/usr/local/JDK17
export CLASSPATH=.:$JAVA_HOME/lib
export PATH=.:$JAVA_HOME/bin:$JAVA_HOME/lib:$PATH

刷新环境变量配置

1
$ source /etc/profile

如果使用上述命令,再使用java --version命令查看版本信息为如下结果则说明成功

1
2
3
4
5
root@VM-0-7-ubuntu:/usr/local# java --version
java 17.0.1 2021-10-19 LTS
Java(TM) SE Runtime Environment (build 17.0.1+12-LTS-39)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.1+12-LTS-39, mixed mode, sharing)
root@VM-0-7-ubuntu:/usr/local# 

否则需要停掉本机JVM程序,然后重启服务器主机,重启后再使用java --version命令验证

7.6、编写Demo测试一下

1
2
3
4
5
6
7
8
9
// Demo.java
public class Demo{
        public static void main(String[] args){
                System.out.println("Hello World");
                System.out.println(System.getProperty("java.version"));
                System.out.println(System.getProperty("java.home"));
                System.out.println(System.getProperty("os.name"));
        }
}


7.7.验证安装结果

1
2
3
4
5
~$ java Demo.java
Hello World
17
/usr/local/JDK17
Linux

迁移成功,撒花!!!后续可以开始服务端的部署工作了。


总结

        本次迁移测试发现,从JDK11迁移至JDK17的困难程度成度要远小于JDK8迁移至JDK11的时候,之前有预感中间会有坑,不过整体迁移下来,除了前期第三方依赖的不兼容、不支持问题及JDK的安全机制限制外,其他的问题都通过网络搜索很快得到解决,总体来说本次迁移过程比较顺利,比预期的快了很多,后续如有新问题会再同步更新笔记。


参考


|15707字|1132阅读
         
返回顶部