随机技术的发展JDK开发工具不断迭代,目前公司所用的JDK8已经落后于时代技术趋势,一些新的技术特性无法在项目中使用。另外Springboot3的最低JDK版本要求JDK17。升级到 JDK 17(长期支持版本,LTS)具有多方面的优势,无论是从技术、性能、安全性还是未来生态支持的角度来看,都是值得考虑的。 为了安全、稳定、平滑的过度到SpringBoot3,故先对基础镜像的JDK升级到17。Spring官方推荐的JDK厂商是BellSoft。
业务发展需要接入到AI Chat接口,大家都知道AI的响应时间较长通常需要1-5秒才能响应完成。传统的阻塞式IO已经不能满足对三方慢接口调用的需求,阻塞IO用于慢接口对系统稳定性是比较大的挑战。我们需要使用WebFlux采用非阻塞式IO、Reactive响应式编程。故开始调研采用WebFlux技术后的兼容性。
OpenFeign声明式不能兼容WebFlux、三方的feign-reactive框架不兼容现SpingBoot版本,兼容问题只能选择WebClient的过度。
正在考虑的SpringBoot3.x升级,现有的Springboot2.x社区已经停止维护,无法使用新的框架特性。
Spring Framework、SpringBoot、SpringCloud、SpringCloudAlibaba这些组件对版本一致性要求也高,兼容问题会踩较多的坑。最终决定首先升级JDK 再过度到Spirngboot3.x。
Spring Boot 2.x 的最终版本是 2.7.x(2022年11月停止维护),其设计时基于 JDK 8~17 测试,未针对 JDK 21 适配。
Spring Boot 3.x(2022年11月发布)才是官方支持 JDK 17~21 的版本(需 Spring Framework 6+)
某些功能(如Lombok、AOP)可能失效。
第三方库(如数据库驱动、Redis客户端)可能不兼容 JDK 21。
JDK 17 是 Oracle 官方长期支持版本(LTS,支持到 2029年),而 JDK 8 的支持已逐渐减少(企业需付费扩展支持)。
垃圾回收(GC)改进:ZGC(低延迟垃圾回收器)和 Shenandoah GC 在 JDK 17 中更成熟,适合高吞吐、低延迟场景。
JIT 编译器优化:GraalVM 等技术的引入提升了运行时性能。
启动速度:JDK 9+ 的模块化系统(JPMS)减少了启动时间和内存占用。
Switch 表达式(JDK 14+):简化代码,支持模式匹配。
文本块(Text Blocks)(JDK 15+):方便处理多行字符串。
Record 类(JDK 16):简化不可变数据类的定义。
密封类(Sealed Classes)(JDK 17):限制类的继承关系,增强安全性。
模式匹配(Pattern Matching):简化 instanceof
和类型转换操作。
移除或废弃不安全/过时的 API(如 Security Manager
已标记为废弃)。
更强的加密算法支持(如 TLS 1.3 默认启用)。
漏洞修复:旧版本(如 JDK 8)的已知漏洞在新版本中被修复。
HTTP/2 客户端(标准 API,替代老旧的 HttpURLConnection
)。
Vector API(JDK 16+):优化数值计算性能。
Foreign Function & Memory API(JDK 17):替代 JNI,更安全地调用本地代码。
JDK 10+ 对 Docker 等容器环境的资源限制(CPU/内存)感知更好。
Spring 6 / Spring Boot 3 已强制要求 JDK 17+。
新框架和工具(如 Quarkus、Micronaut)优先支持新 JDK。
JDK 17 的 OpenJDK 版本可免费商用。
这点是在webflux-service做响应式验证的时候使用了JDK17 , 在整个Spring Framework5 + Springboot2.x + SpringCloud Hoxton.SR9 版本下没有出现大的问题,证明现有架构下升级到JDK17是可行的,但是也需要关注运行时的潜在问题。
另一方面是前期在流水线升级BellSoft-JDK17阶段性的调试成功,JDK17自定义镜像打包成功,标志着运行环境升级JDK17可以全面铺开。
现有的CI/CD流水线中,其中maven构建环境升级到JDK17, 服务的运行基础镜像升级到JDK17,采用新的流水线脚本
kind: template
load: drone_deploy_jdk17_jar.yaml
data:
name: ${DRONE_REPO_NAME}
kind: template load: drone_deploy_jar.yaml data: name: ${DRONE_REPO_NAME}
\\192.168.12.97\软件工具\Java开发工具\JDK17
错误的原因是因为 JVM 的模块 java.base 没有对未命名的模块开放 java.lang 这个包的深度反射 API 的调用权限。 具体来说,是没有开放 setAccessible(true) API。
这个问题在 JDK 8 以及以上的版本容易遇到。 解决的方法是在启动 Java 应用的时候, 加上参数指定开放特定的 Module/Package,使得 unnamed module 可以访问指定的 package 下面的深度反射 API。 如果有多个 Package 需要开放深度反射 API,那么可以指定多个 --add-opens 参数。
加上JVM参数配置:
--add-opens java.base/java.lang=ALL-UNNAMED 上面的包名称根据报错中的opens后面的内容添加,因此根据上面报错,应该添加如下所示: --add-opens java.base/java.util=ALL-UNNAMED
相关文章:https://zhuanlan.zhihu.com/p/590864324
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.xxx.tech.workorder.api.ApiWorkOrder': FactoryBean threw exception on object creation; nested exception is java.lang.reflect.InaccessibleObjectException: Unable to make field static final java.lang.invoke.MethodHandles$Lookup java.lang.invoke.MethodHandles$Lookup.IMPL_LOOKUP accessible: module java.base does not "opens java.lang.invoke" to unnamed module @1a87b51
原因 :Maven: jakarta.annotation:jakarta.annotation-api:1.3.5 依赖与org.apache.tomcat:annotations-api:6.0.53 依赖的类冲突导致无法找到 lookup,解决办法去除对应的tomcat的annotations-api依赖,因为jakarta转正了
Caused by: java.lang.NoSuchFieldError: REFLECTION
at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:456)
从 JDK 11 开始,JAXB 已被完全移除,需要手动添加依赖,这个代码预security有关系,jdk11以上会自动加jaxb依赖。
将jaxb-impl依赖版本调整为jaxb-api 2.3.1 版本一致,问题解决。
177[ERROR] /drone/src/src/main/java/com/xxx/tech/activity/service/fkw/FkwService.java:[29,16] cannot find symbol
178[ERROR] symbol: class BASE64Encoder
179[ERROR] location: package sun.misc
问题原因:引用了不稳定的类,在新版本jdk中该类被移出了。
sun.misc.BASE64Encoder
是 JDK 内部 API,从 Java 8 开始就被标记为不推荐使用(deprecated),在更高版本的 JDK 中可能被移除。官方推荐使用 java.util.Base64
替代。 这种用法在 JDK 9+ 会失效(因模块化系统)不同 JDK 厂商(如 Oracle/OpenJDK/IBM等)可能不存在这个类
// Java 8+ 标准方式 import java.util.Base64; Base64.Encoder encoder = Base64.getEncoder(); String encoded = encoder.encodeToString(data.getBytes()); Base64.Decoder decoder = Base64.getDecoder(); byte[] decoded = decoder.decode(encoded);
[ERROR] /drone/src/src/main/java/com/xxx/tech/payment/enums/CommonConstant.java:[11,2] cannot find symbol
[ERROR] symbol: class Reference
编译失败,原因:开发者不知情的情况下 引入了@Reference该注解,升级jdk17后导致编译报错。解决办法去除相关代码。
同类问题:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project dashboard-service-cloud: Compilation failure
[ERROR] /drone/src/src/main/java/com/xxx/platform/dashboard/server/utils/DateUtils.java:[5,48] package jdk.nashorn.internal.objects.annotations does not exist