0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

JDK从8升级到21的问题集

京东云 来源:jf_75140285 作者:jf_75140285 2025-06-06 16:49 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、背景与挑战

1.升级动因

◦Oracle长期支持策略

◦现代特性需求:协程、模式匹配、ZGC等

◦安全性与性能的需求

AI新技术引入的版本要求

2.项目情况

◦100+项目并行升级的协同作战

◦多技术栈并存

◦持续集成体系的适配挑战



二、进度

应用总数 已完成 应用下线 待升级
100+ 73 13 10+



三、主要问题域与解决方案

1. 依赖管理的"蝴蝶效应"

•sun.misc.BASE64Encoder等内部API废弃 → 引发编译错误

•JAXB/JAX-WS从JDK核心剥离 → XML处理链断裂

•Lombok与新版编译器兼容性问题(尤其record类型)

核心原因在于JEP320提案:https://openjdk.org/jeps/320



案例1:历史SDK的编译陷阱

Compilation failure: Compilation failure:
#14 4.173 [ERROR] 不再支持源选项 6。请使用 8 或更高版本。
#14 4.173 [ERROR] 不再支持目标选项 6。请使用 8 或更高版本。

< !-- 旧版本编译器配置导致构建失败 -- >
< plugin >
    < groupId >org.apache.maven.plugins< /groupId >
    < artifactId >maven-compiler-plugin< /artifactId >
    < version >3.5< /version >
    < configuration >
        < source >1.6< /source >
        < target >1.6< /target >
    < /configuration >
< /plugin >

< plugin >
    < groupId >org.apache.maven.plugins< /groupId >
    < artifactId >maven-compiler-plugin< /artifactId >
    < version >3.13.0< /version >
    < configuration >
        < release >8< /release >< !-- 统一使用release参数 -- >
    < /configuration >
< /plugin >

运行 HTML

案例2:JAXB的模块化剥离

javax.xml.bind.JAXBException:Implementation of JAXB-API has not been found

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

案例3:Lombok与新版编译器兼容性问题

java: java.lang.NoSuchFieldError

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

案例4:Resource注解找不到

Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.annotation.Resource.lookup()'
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.< init >(CommonAnnotationBeanPostProcessor.java:664)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.lambda$buildResourceMetadata$0(CommonAnnotationBeanPostProcessor.java:395)
at org.springframework.util.ReflectionUtils.doWithLocalFields(ReflectionUtils.java:669)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.buildResourceMetadata(CommonAnnotationBeanPostProcessor.java:377)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.findResourceMetadata(CommonAnnotationBeanPostProcessor.java:358)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(CommonAnnotationBeanPostProcessor.java:306)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:1116)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
... 37 more

< dependency >
    < groupId >jakarta.annotation< /groupId >
    < artifactId >jakarta.annotation-api< /artifactId >
    < version >1.3.5< /version >
< /dependency >

< dependency >
    < groupId >javax.annotation< /groupId >
    < artifactId >javax.annotation-api< /artifactId >
    < version >1.3.2< /version >
< /dependency >

上述两个依赖代码基本一样,推荐使用该版本:

jakarta.annotation:jakarta.annotation-api。



2. 模块化的破与立

反射访问的模块墙

[ERROR] Unable to make field private int java.text.SimpleDateFormat.serialVersionOnStream accessible

# 启动参数添加模块开放配置
--add-opens java.base/java.text=ALL-UNNAMED
--add-opens java.base/java.lang.reflect=ALL-UNNAMED

完整模块开放配置模板

export JAVA_OPTS="-Djava.library.path=/usr/local/lib -server -Xmx4096m --add-opens java.base/sun.security.action=ALL-UNNAMED
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.math=ALL-UNNAMED
--add-opens java.base/java.util=ALL-UNNAMED
--add-opens java.base/sun.util.calendar=ALL-UNNAMED
--add-opens java.base/java.util.concurrent=ALL-UNNAMED
--add-opens java.base/java.util.concurrent.locks=ALL-UNNAMED
--add-opens java.base/java.security=ALL-UNNAMED
--add-opens java.base/jdk.internal.loader=ALL-UNNAMED
--add-opens java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED
--add-opens java.base/java.net=ALL-UNNAMED
--add-opens java.base/sun.nio.ch=ALL-UNNAMED
--add-opens java.management/java.lang.management=ALL-UNNAMED
--add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED
--add-opens java.management/sun.management=ALL-UNNAMED
--add-opens java.base/sun.security.action=ALL-UNNAMED
--add-opens java.base/sun.net.util=ALL-UNNAMED
--add-opens java.base/java.time=ALL-UNNAMED
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
--add-opens java.base/java.io=ALL-UNNAMED"

3. 语法层面的"时空穿越"

案例1:Base64编解码改造

// JDK8写法(已废弃)
BASE64Encoder encoder =newBASE64Encoder();
String encoded = encoder.encode(data);
// JDK21规范写法
Base64.Encoder encoder =Base64.getEncoder();
String encoded = encoder.encodeToString(data);

案例2:日期序列化问题

Caused by:java.lang.reflect.InaccessibleObjectException: 
Unable to make field private int java.text.SimpleDateFormat.serialVersionOnStream accessible

解决方案

1.使用DateTimeFormatter替代SimpleDateFormat

2.或添加模块开放参数:--add-opens java.base/java.text=ALL-UNNAMED



4. 隐秘的"依赖战争"

注解包冲突典型案例

[ERROR] javax.annotation.Resource exists in both 
jsr250-api-1.0.jar and jakarta.annotation-api-1.3.5.jar

< !-- 统一使用Jakarta标准 -- >
< dependency >
    < groupId >jakarta.annotation< /groupId >
    < artifactId >jakarta.annotation-api< /artifactId >
    < version >2.1.1< /version >
< /dependency >
< !-- 排除旧版本依赖 -- >
< exclusions >
    < exclusion >
        < groupId >javax.annotation< /groupId >
        < artifactId >jsr250-api< /artifactId >
    < /exclusion >
< /exclusions >

5. 构建体系的改造

Maven插件兼容性问题

[ERROR] The plugin org.apache.maven.plugins:maven-compiler-plugin:3.13.0 
requires Maven version 3.6.3

升级策略

1.升级Maven版本

2.统一插件版本


    < pluginManagement >
        < plugins >
            < plugin >
                < groupId >org.apache.maven.plugins< /groupId >
                < artifactId >maven-compiler-plugin< /artifactId >
                < version >3.13.0< /version >
            < /plugin >
            < plugin >
                < groupId >org.apache.maven.plugins< /groupId >
                < artifactId >maven-war-plugin< /artifactId >
                < version >3.4.0< /version >
            < /plugin >
        < /plugins >
    < /pluginManagement >
< /build >

四、最佳实践总结

1. 本地编译

第一步:在本地进行编译,提前识别出语法错误、版本冲突及不兼容问题。

主要有以下几种场景:

Base64:参照 【Base64编解码改造】

lombok:升级版本

jsr250、jaxb-runtime、jakarta.annotation-api:参照 【注解包冲突典型案例】

maven-compiler-plugin:升级版本

maven-resources-plugin:升级版本

maven-war-plugin:升级版本





2. 行云构建

同【本地编译】



3. 行云部署

a、镜像不匹配:自定义镜像或者使用已申请的jdk21镜像

b、module权限不够:参照【完整模块开放配置模板

c、JDSecurity加解密

所有数据库操作:important.properties配置文件的处理方式

classpath:important.properties 使用PropertyPlaceholderConfigurer进行处理,不要用JDSecurityPropertyFactoryBean。

< !--    -- >
< !--       < property name="ignoreResourceNotFound" value="true" / >-->
< !--       < property name="secLocation" value="classpath:important.properties"/ >-->
< !--    < /bean >-->



4. 运行

a、序列化异常

jdk21使用列表视图作为入参,导致jsf接口进行反序列化报错。报错代码如下:

List< String > subList = venderCodes.subList(i * batchSize, Math.min(venderCodes.size(), (i + 1) * batchSize));
VendorQueryVo vendorQueryVo = new VendorQueryVo();
vendorQueryVo.setVendorCodes(subList);
// 该接口最多支持100条调用
List< VendorVo > batchVendorNameByVendorCode = vendorBaseInfoService.getBatchVendorNameByVendorCode(vendorQueryVo, I18NParamFactory.getJDI18nParam());

将 vendorQueryVo.setVendorCodes(subList) 修改为vendorQueryVo.setVendorCodes(new ArrayList<>(subList)) 即可解决问题



b、线程上下文类找不到:使用多线程场景下尽可能使用显式指定线程池【默认情况下 不同运行环境的处理机制不同】





5. JVM调优

垃圾回收调优

UseParallelGC、UseG1GC和UseZGC是 Java 虚拟机(JVM)中三种不同的垃圾回收器(Garbage Collector, GC),它们的设计目标和使用场景有所不同。以下是它们的区别:

特性 UseParallelGC UseG1GC UseZGC
设计目标 高吞吐量 平衡吞吐量和延迟 极低延迟
暂停时间 较长 较短 极短
适用堆大小 中小堆(几 GB 到几十 GB) 大堆(几十 GB 到几百 GB) 超大堆(TB 级别)
CPU 消耗 中等 中等 较高
适用场景 批处理、计算密集型任务 对延迟有一定要求的应用 对延迟极其敏感的应用

•如果你的应用对吞吐量要求高,且可以接受较长的暂停时间,选择UseParallelGC

•如果你的应用对延迟有一定要求,且堆内存较大,选择UseG1GC

•如果你的应用对延迟极其敏感,且堆内存非常大,选择UseZGC

仅供参考,具体请按照实际情况来进行调整。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JDK
    JDK
    +关注

    关注

    0

    文章

    83

    浏览量

    17206
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    如何在 EB Tresos 工作区中升级 RTD 驱动程序?

    配置工作区在 CAN 和以太网模块上都能成功运行。 我现在计划将 RTD (MCAL) 驱动程序版本 2.0.0 升级到 5.0.0。我想了解使用 EB Tresos 更新驱动程序版本和重新生成模块的过程,最好是利用现有工作区作为基础。 您能否指导我执行此
    发表于 04-27 07:22

    为什么OCPP充电桩Security Profile要升级到2/3?

    现在新建或改造充电桩时,一般不再允许只停留在OCPP1.6的SecurityProfile0/1,要求升级到Profile2/3,核心原因可以归纳为“合规+安全+运营风险”三方面。深圳惠志科技推出
    的头像 发表于 03-02 17:40 1617次阅读
    为什么OCPP充电桩Security Profile要<b class='flag-5'>升级到</b>2/3?

    匠芯创D21x芯片驱动两轮电动车智慧升级

    、安全与交互于一体的智能核心。 近日,小牛电动推出的符合新国标的车型U3,搭载了基于匠芯创工业人机交互MPU D21x系列芯片的全尺寸TFT智能仪表方案。该方案凭借流畅的交互与可靠的性能,为用户提供了
    发表于 02-06 15:42

    深圳南柯电子|新能源电子EMC整改:技术攻坚产业升级的工程

    深圳南柯电子|新能源电子EMC整改:技术攻坚产业升级的工程
    的头像 发表于 11-25 10:03 472次阅读

    嵌入式入门必看!迅为RK3568 V2.0升级,新手也能轻松玩转

    嵌入式入门必看!迅为RK3568 V2.0升级,新手也能轻松玩转
    的头像 发表于 10-28 13:26 697次阅读
    嵌入式入门必看!迅为RK3568 V2.0<b class='flag-5'>升级</b>,新手也能轻松玩转

    V5.0.0 ps 打印显示线程 error 状态全为 EINTRPT,,为什么?

    最近我将RTT版本升级了一下,4.1.1升级到5.0.0,运行时通过控制台 ps之指令观察,发现线程 error 都报 EINTRPT, 但 4.1.1 时都是 OK. 以下是 RTT 为 4.1.1 时的 ps 反馈 以下
    发表于 10-13 06:46

    明远智睿RK3568核心板如何助力工业4.0升级

    汽车工厂效率提升30%看:明远智睿RK3568核心板如何助力工业4.0升级 工业4.0的核心在于通过智能化技术实现生产效率的提升与生产模式的变革,而核心元器件作为工业设备的“心脏”,其性能直接影响
    的头像 发表于 09-04 17:42 1080次阅读

    “代步工具”“智能伙伴”,存储如何支撑汽车升级之路

    我们手里的手机,功能机“飞升”智能机,经历了几个关键阶段: 第一步,是交互方式的革新——按键触摸大屏,让操作更直观流畅; 第二步,是软件系统的
    的头像 发表于 08-21 16:36 866次阅读
    <b class='flag-5'>从</b>“代步工具”<b class='flag-5'>到</b>“智能伙伴”,存储如何支撑汽车<b class='flag-5'>升级</b>之路

    400G 升级到 800G,到底能省多少钱?(洞察 TCO 真相)

     觉得800G光模块采购价高?本文揭示400G升级800G的惊人TCO节省:硬件总成本降25%,每Gbps电费省30%,运维效率提30%,空间占用减半!3年总体拥有成本直降30%+,远超初期投入。算清这笔账,升级800G不再是
    的头像 发表于 08-11 10:39 1173次阅读

    ModbusProfinet:功率表通信升级的技术挑战与解决方案

    在制造行业的自动化升级浪潮中,如何将车间里大量仍在服役的Modbus功率表,经济高效地接入全新的Profinet工业以太网中?这不仅是技术选型题,更是考验工程师智慧的实践题。本文将为您剖析这一升级
    的头像 发表于 08-04 14:49 675次阅读
    <b class='flag-5'>从</b>Modbus<b class='flag-5'>到</b>Profinet:功率表通信<b class='flag-5'>升级</b>的技术挑战与解决方案

    讯飞星火X1升级版正式上线

    今天,基于全国产算力训练的深度推理大模型——讯飞星火X1升级版正式上线。
    的头像 发表于 07-30 14:12 2286次阅读
    讯飞星火X1<b class='flag-5'>升级</b>版正式上线

    旧款升级到树莓派5,你必须注意的几个问题!

    。树莓派5性能提升导致发热量增加,可能需要投资散热方案以优化性能。尽管树莓派5无疑是当前树莓派家族中的佼佼者,但性能基准测试并不能说明全部问题。在升级之前,需考虑树
    的头像 发表于 07-02 16:22 1685次阅读
    <b class='flag-5'>从</b>旧款<b class='flag-5'>升级到</b>树莓派5,你必须注意的几个问题!

    STM32MP157d linux5.4.31升级到6.1.82无法启动怎么解决?

    我以前一直使用linux5.4.31,只使用了TFA没有optee uboot是2020版本。一直用得好好的 上个礼拜我想升级到6.1.82(主要想打RT linux patch, 看到STM有出
    发表于 06-10 07:31

    STM32MP157d linux5.4.31升级到6.1.82无法启动怎么解决?

    我以前一直使用linux5.4.31,只使用了TFA没有optee uboot是2020版本。一直用得好好的 上个礼拜我想升级到6.1.82(主要想打RT linux patch, 看到STM有出
    发表于 06-06 06:42

    STM32MP157d linux5.4.31升级到6.1.82无法启动怎么解决?

    我以前一直使用linux5.4.31,只使用了TFA没有optee uboot是2020版本。一直用得好好的 上个礼拜我想升级到6.1.82(主要想打RT linux patch, 看到STM有出
    发表于 05-21 06:20