JDK 8 升级 JDK 17 全流程教学指南

news2024/11/15 9:16:01

JDK 8 升级 JDK 17

首先已有项目升级是会经历一个较长的调试和自测过程来保证允许和兼容没有问题。先说几个重要的点

  1. 遇到问题别放弃
  2. 仔细阅读报错,精确到每个单词每一行,不是自己项目的代码也要点进去看看源码到底是为啥报错
  3. 明确你项目引入的包,升级到 JDK17 后对应低版本的都需要升级

可能大部分同学都不是完全了解自己的项目都依赖了什么包,这个升级工作一定会加深你对 maven 包管理的理解,以及你对你项目依赖的熟悉程度和你解决排查问题的能力。

项目跑不起来就慢慢调试,问题暂时解决不了就放一放,放松一下,交给下个阶段头脑清醒的自己。

升级你的 maven 编译版本

修改你主工程的 pom 文件

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.7.0</version>
  <configuration>
    <source>17</source>
    <target>17</target>
  </configuration>
</plugin>

我用的是 idea 修改你项目的编译环境

在这里插入图片描述

从新拉 maven 之后你就可以看看哪里报红哪里需要改了,别担心,噩梦才刚刚开始哈哈哈

去除重复依赖

长时间的维护,可能存在一个包在一个 pom 里引入两次的情况 (真服了)

首先项目中 pom 文件不可以出现重复依赖,需要排查去掉

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
</dependency>

对于依赖版本,不可以直接出现 RELEASE,你可以定义一个 properties 然后引用一下

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <version>RELEASE</version>
  <scope>test</scope>
</dependency>

一些依赖的版本升级

这部分只列举我再升级过程中遇到的需要升级的问题

升级 lombok 到 1.18.26

lombok 得用新版本 我之前是 1.18.4 现在换到 26

<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.18.26</version>
</dependency>

升级 springboot 到 2.7.14

你可以在官方文档看到 2.7.14 对应的一些依赖版本

https://docs.spring.io/spring-boot/docs/2.7.14/reference/html/dependency-versions.html#appendix.dependency-versions

<spring.boot.version>2.7.14</spring.boot.version>
<spring.version>5.3.29</spring.version>
<dubbo.version>2.7.23</dubbo.version>

说一下我这里为什么没有选择拥抱 3.x ,因为 dubbo 3 才支持 springboot 3.x 和 spring6.x,而我调用的三方接口都是 dubbo2,dubbo3 应用基本注册不向下兼容 dubbo2,会有诸多问题,所以这里选择

2.7.14 GA 这个官网稳定支持的版本,如果你没有这个问题,可以选择拥抱 3.0

提醒一下如果要升级 springboot3

springboot3 弃用了 javax.servlet.http.HttpServletRequest; 需要替换为 jakarta.servlet.http.HttpServletRequest;

HandlerInterceptorAdapter 被删除了,由 HandlerInterceptor 来代替

yml 配置允许循环依赖

spring:
  main:
    allow-circular-references: true

三方包依赖找不到类

我引入的三方包,Spring bean 加载存在问题,感觉是 JDK 升级的问题,跟 spring 的升级没关系

是找不到这个玩意的定义 org.apache.commons.configuration.interpol.ConfigurationInterpolator

nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.apache.commons.configuration.interpol.ConfigurationInterpolator

很怪,明明有就找不到,这里将三方包的引入排除掉,自己项目中单独进行引入

<exclusion>
  <artifactId>commons-configuration</artifactId>
  <groupId>commons-configuration</groupId>
</exclusion>

<dependency>
  <groupId>commons-configuration</groupId>
  <artifactId>commons-configuration</artifactId>
  <version>1.10</version>
</dependency>

顺便提一个 springbean 加载的问题,如果你引入的三方包有路径下的 bean 需要你进行注册管理,你项目启动类的扫描路径下需要包含他的路径,比如

@SpringBootApplication(scanBasePackages = {"com.你的包","com.三方的需要扫描的包路径"})

当然,如果路径一致,就一个就可以

zookeeper 升级 3.5.10

升级 zookeeper 版本为 3.5.10 , 3.5.x 以下不兼容 JDK17

https://curator.apache.org/zk-compatibility-34.html 还有个 curator 强依赖的场景需要注意升级

如果你服务器的 zookeeper 可以升级最好不过,如果不能

curator 2.x 可以兼容 zookeeper 3.5.x 的版本

如果你之前使用的是 curator 2.x 就只升级 zookeeper 的版本就行了,这样连接你线上的 zookeeper 不会有问题。

否则请将服务器版本同步升级

可参考文章:

官方文章 https://curator.apache.org/zk-compatibility-34.html

csdn 文章 https://blog.csdn.net/wo541075754/article/details/69138878

<apache-curator.version>2.12.0</apache-curator.version>
<dependency>
  <groupId>org.apache.curator</groupId>
  <artifactId>curator-framework</artifactId>
  <version>${apache-curator.version}</version>
  <exclusions>
    <exclusion>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.apache.zookeeper</groupId>
      <artifactId>zookeeper</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.apache.curator</groupId>
  <artifactId>curator-recipes</artifactId>
  <version>${apache-curator.version}</version>
  <exclusions>
    <exclusion>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.apache.zookeeper</groupId>
      <artifactId>zookeeper</artifactId>
    </exclusion>
  </exclusions>
</dependency>

mysql 版本升级 8.0.33

没啥好说的,不升你连不上

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.33</version>
</dependency>

启动项

注意你项目启动时需要增加启动参数,不管是实际运行还是本地调试运行

--add-opens
java.base/java.lang=ALL-UNNAMED
--add-opens
java.base/java.io=ALL-UNNAMED
--add-opens
java.base/java.math=ALL-UNNAMED
--add-opens
java.base/java.net=ALL-UNNAMED
--add-opens
java.base/java.nio=ALL-UNNAMED
--add-opens
java.base/java.security=ALL-UNNAMED
--add-opens
java.base/java.text=ALL-UNNAMED
--add-opens
java.base/java.time=ALL-UNNAMED
--add-opens
java.base/java.util=ALL-UNNAMED
--add-opens
java.base/JDK.internal.access=ALL-UNNAMED
--add-opens
java.base/JDK.internal.misc=ALL-UNNAMED

当然你如果不加也能起可以不加。解释一下

--add-opens 参数是在 JDK 9 及更高版本中引入的,用于在模块系统中打开特定的包以实现反射访问。模块系统引入了更严格的访问控制,以确保代码的可靠性和安全性。在某些情况下,一些库或框架可能依赖于 JDK 内部的类和方法,这些类和方法在模块系统中是受限的,因此需要通过 --add-opens 参数进行显式打开。

具体来说,--add-opens 参数允许你在指定的模块中打开某个包,以便其他模块可以通过反射访问该包中的类和方法。java.base 是 JDK 的基础模块,其中包含了 Java 核心类库。使用 --add-opens java.base/java.lang=ALL-UNNAMED 参数是为了在 JDK 9 及更高版本中允许在 java.base 模块中的 java.lang 包中打开所有未命名的类,从而允许反射访问。

通常情况下,如果你的应用代码遵循良好的编程实践,是不需要使用 --add-opens 参数的。然而,一些第三方库、框架或老旧的代码可能会依赖于 JDK 内部的特性,这时可能会需要使用这个参数来解决访问限制问题。不过,尽量避免在生产环境中过度依赖这种方式,因为这可能会引入一些潜在的风险和不稳定性。

比如

import sun.misc.Unsafe;

public class RestrictedAccessExample {
    public static void main(String[] args) {
        try {
            // 使用反射获取 Unsafe 类的实例
            Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
            Unsafe unsafe = (Unsafe) unsafeClass.getDeclaredField("theUnsafe").get(null);

            // 使用 Unsafe 实例调用内部方法
            long value = 42;
            long address = unsafe.allocateMemory(8);
            unsafe.putLong(address, value);

            System.out.println("Value at address: " + unsafe.getLong(address));
        } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

全部启动项示例

当然你之前的垃圾回收器可能还在用 CMS ,那已经废弃了,所以需要改,用 G1 或者 ZGC 吧,这里我推荐直接用 ZGC。

ZGC 在 17 中已经非常成熟

-Xms2G -Xmx2G -XX:MaxDirectMemorySize=256M -XX:ThreadStackSize=512 -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M -XX:-OmitStackTraceInFastThrow -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ZAllocationSpikeTolerance=5 -Xlog:gc:/logs/gc.log 
--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.base/java.time=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/jdk.internal.access=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED  -jar dyinggq.jar

详细参数配置根据自己服务自行适配调整。

报错集

这里收录一下报错和解决方案

nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.apache.commons.configuration.interpol.ConfigurationInterpolator

这个找不到类,找到对应的调用位置,看看为啥没有。最后解决方案是排除了三方包的引入,自行单独引入该包

<exclusion>
  <artifactId>commons-configuration</artifactId>
  <groupId>commons-configuration</groupId>
</exclusion>

<dependency>
  <groupId>commons-configuration</groupId>
  <artifactId>commons-configuration</artifactId>
  <version>1.10</version>
</dependency>

这个报错是你 zookeeper 的客户端包版本不兼容你服务器的版本

Caused by: java.lang.IllegalStateException: KeeperErrorCode = Unimplemented for 

org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperClient.createEphemeral(CuratorZookeeperClient.java:114)
	at org.apache.dubbo.remoting.zookeeper.AbstractZookeeperClient.create(AbstractZookeeperClient.java:83)
	at org.apache.dubbo.registry.zookeeper.ZookeeperRegistry.doRegister(ZookeeperRegistry.java:125)
	... 77 common frames omitted

这里是因为我当时升级 zookeeper 的时候 curator 也一起升到 3.x 了,而线上服务 zookeeper 的版本是 3.4.x

<apache-curator.version>2.12.0</apache-curator.version>

所以 curator 还用老版本

dubbo No such extension cid for loadbalance/org.apache.dubbo.rpc.cluster.LoadBalanced

dubbo 找不到自定义的 Balance ,这个有很多情况,我说我的情况,我的情况是项目服务还在使用

com.alibaba.dubbo ,然后我想一起升级到 org.apache.dubbo ,结果找不到了,想来是路径的问题,老的都是继承的

com.alibaba.dubbo .rpc.cluster.LoadBalanced 你升级了需要org.apache.dubbo.rpc.cluster.LoadBalanced

这个如果你依赖三方包的,还真改不了,好在,之前版本的 dubbo 也能在 jdk17 下运行。

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut aspect

这个是 aspectj 版本不匹配

排除其他包引入的 aspecj 引入对应 springboot 版本的 aspecj ,我这里给的是 springboot 2.7.14 对应的

<aspectjweaver.version>1.9.7</aspectjweaver.version>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>${aspectjweaver.version}</version>
</dependency>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/853779.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是碳中和认证申请气候友好证绿色标?

碳中和认证几乎所有卖家都适用&#xff0c;需要的资料比较简单&#xff0c;几乎所有的产品及所有的站点都可以做。 一、“碳中和”认证是什么&#xff1f; 碳中和认证是通过计算碳排放&#xff0c;减少碳排放&#xff0c;进而减少使地球变暖的温室气体的数量的一个认证。是亚…

Qt多线程编程

本章介绍Qt多线程编程。 1.方法 Qt多线程编程通常有2种方法&#xff1a; 1)通过继承QThread类&#xff0c;实现run()方法。 2)采用QObject::moveToThread()方法。 方法2是Qt官方推荐的方法&#xff0c;本文介绍第2种。 2.步骤 1)创建Worker类 这里的Worker类就是我们需要…

CSS:盒子模型 与 多种横向布局方法

目录 盒子模型块级盒子内联级盒子内联块级盒子弹性盒子display 改变模型区域划分text 内容区padding 填充区border 边框区margin 外边距直接设置盒子大小 布局横向布局方法一 float 浮起来方法二 内联块级元素实现方法三 弹性盒子模型 盒子模型 块级盒子 独占一行&#xff0c…

打破雇佣思想 云畅科技CIO曾颖博士浅析零雇工模式

作者简介 INTRO 曾 颖 工商管理博士 云畅科技高级合伙人、CIO 产业咨询&#xff06;企业数字化转型落地专家 2018年&#xff0c;“零雇工”企业组织创新2018全球创新创业教育高峰论坛在西安举行&#xff0c;我当时作为上海沐新众创空间的导师和分会场“企业家如何创建零雇工…

4G型无线液位变送器是什么?

4G型无线液位变送器采用了四代无线通讯技术&#xff0c;与普通液位计相比&#xff0c;免去了布线的烦恼&#xff0c;无需时刻监控现场&#xff0c;在大幅提高工作效率和减少人力成本的同时&#xff0c;还可以随时随地获取监测数据。 4G型无线液位变送器的功能优势&#xff1a;…

Unico-GUI软件关于ST传感器机器学习(MLC)基本操作步骤

准备工作 UNICO-GUI软件用于意法半导体产品组合&#xff08;加速度计、陀螺仪、磁力计和环境传感器&#xff09;中所有MEMS传感器的评估板。它可用于Linux&#xff08;基于Debian&#xff09; / Mac OS X / Windows平台。 Unico-GUI - MEMS evaluation kit software package …

hcip的重发布实验(2)

题目 拓扑图 IP地址和环回的配置 R1 <Huawei>sy Enter system view, return user view with CtrlZ. [Huawei]sysname r1 [r1]int l0 [r1-LoopBack0]ip add 1.1.1.1 24 [r1-LoopBack0]int g0/0/0 [r1-GigabitEthernet0/0/0]ip add 12.1.1.1 24 Aug 9 2023 10:38:48-08:…

文件上传漏洞(webshell)和文件包含漏洞

一、防护 1、防护 1、判断文件后缀&#xff0c;为图片的话才让上传成功。 2、解析文件内容&#xff08;文件幻数&#xff09;判断文件头和文件尾部是否一致 幻数 常见的 3、隐藏按钮&#xff08;带上code唯一值&#xff09; 4、二次渲染&#xff08;类似拿着你的图片&#xff…

最大子数组和【力扣53】

一、解题思路 Max[i]表示&#xff1a;以nums[i]为开头的所有连续子数组和的最大值。 由此可以推出Max[i-1]和Max[i]的关系&#xff1a; 若Max[i]>0&#xff1a;Max[i-1]nums[i-1]Max[i]&#xff1b; 否则&#xff1a;Max[i-1]nums[i-1]&#xff1b; 则ansMAX&#xff0…

Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架

简单手写SpringIOC框架 环境搭建基于XML方式项目结构项目代码运行结果 基于注解方式项目结构项目代码运行结果 简单手写SpringIOC框架核心原理基于XML方式原理项目结构项目代码运行结果 基于注解方式原理项目结构项目代码运行结果 环境搭建 基于XML方式 项目结构 项目代码 p…

何时使用MongoDB而不是MySql

什么是 MySQL 和 MongoDB MySQL 和 MongoDB 是两个可用于存储和管理数据的数据库管理系统。MySQL 是一个关系数据库系统&#xff0c;以结构化表格格式存储数据。相比之下&#xff0c;MongoDB 以更灵活的格式将数据存储为 JSON 文档。两者都提供性能和可扩展性&#xff0c;但它…

CGI, FastCGI, WSGI, uWSGI, uwsgi分别是什么?

CGI 1、通用网关接口&#xff08;Common Gateway Interface/CGI&#xff09;,CGI描述了服务器&#xff08;nginx,apache&#xff09;和请求处理程序&#xff08;django,flask,springboot web框架&#xff09;之间传输数据的一种标准. 2.所有bs架构软件都是遵循CGI协议的 3.一…

day10 快速排序 方法重载 和 方法递推

方法重载 斐波拉契数列问题 使用重载思想解决 public static int method(int n){if (n 2 ){return 1 ;}return (n-1)*2method(n-1);}public static int f(int n){if (n 1){return 1;}if (n 2){return 2;}return f(n-1)f(n-2);} 快速排序 思维很简单&#xff0c;类似二…

selenium获取b站视频标题

一、下载selenium 1. 下载对应版本的浏览器驱动 2. 安装selenium 3.把浏览器驱动放到使用的python内核的script目录中 二、测试效果模拟登录b站 from selenium import webdriver from selenium.webdriver.common.by import By import timebrowser webdriver.Chrome() # 打…

使用MyBatis操作数据库

hi,大家好,今天为大家带来MyBatis操作数据库的知识 文章目录 &#x1f437;1.根据MyBatis操作数据库&#x1f9ca;1.1查询操作&#x1f347;1.1.1无参查询&#x1f347;1.1.2有参查询 &#x1f9ca;1.2删除操作&#x1f9ca;1.3修改操作&#x1f9ca;1.4增加操作&#x1f9ca;…

quill 富文本编辑器 @提及

使用插件quill-mention&#xff0c;实现在quill 富文本编辑器使用或#提及用户。 1. 安装 npm install quill-mention --save2. 官方给的示例quill-mention import "quill-mention";const atValues [{ id: 1, value: "Fredrik Sundqvist" },{ id: 2, va…

产线信息化、智能化|汽车座椅产线中的RFID技术方案

引言 在今天的快速发展的制造业中&#xff0c;信息化和智能化已经成为不可或缺的部分。信息化和智能化能够极大地提高生产效率、减少浪费&#xff0c;降低成本&#xff0c;提升产品的质量。汽车座椅产线信息化和智能化是汽车座椅产线升级的重要方向&#xff0c;RFID技术方案在…

大多数单片机程序采用全局变量的形式是为什么呢?

内存占用的可预测性&#xff1a;在单片机程序中&#xff0c;可预测的内存占用是很重要的因素。静态分配可以在编译过程中确定所需的内存&#xff0c;并且分配过程在程序启动之前就已完成。这使得静态分配成为单片机程序的理想选择。栈空间的限制和风险&#xff1a;栈分配具有一…

嘉楠勘智k230开发板上手记录(四)--HHB神经网络模型部署工具

按照K230_AI实战_HHB神经网络模型部署工具.md&#xff0c;HHB文档&#xff0c;RISC-V 编译器和模拟器安装来 一、环境 1. 拉取docker 镜像然后创建docker容器并进入容器 docker pull hhb4tools/hhb:2.4.5 docker run -itd --namehhb2_4 -p 22 "hhb4tools/hhb:2.4.5"…

主调函数与被调函数之间的数据传递

在调用函数时&#xff0c;大多数情况下&#xff0c;主调函数都需要将有关数据传递给被调函数。这就是有参函数。在定义函数时指定的用来接收从主调函数传递过来的值的变量称为形参变量&#xff0c;简称形参&#xff0c;在主调函数的调用函数表达式中&#xff0c;函数名后面圆括…