将 Java 应用从 JDK 8 升级到 JDK 17 是一个重要的版本跨越(包含多个长期支持版本:8→11→17),需要注意以下关键事项:
1. 模块化系统(JPMS)
- JDK 9 引入了模块化系统(Project Jigsaw),JDK 17 继续强化这一特性
- 需处理
java.base
等模块的显式依赖,特别是使用反射访问私有 API 的场景 - 注意
--add-modules
、--add-exports
等启动参数的使用,处理模块封装问题
2. 移除和废弃的 API
- 移除的主要功能:
- 永久代(PermGen)被元空间(Metaspace)替代(JDK 8 已部分完成)
sun.misc.Unsafe
等内部 API 的访问限制加强- 遗留的
com.sun.*
和sun.*
包不再推荐使用
- 废弃的功能:
- 部分 GC 算法(如 CMS)已被标记为废弃
Thread.stop()
等不安全方法的警告增强
3. 语言特性变化
- 需适应新语法:
- 局部变量类型推断(
var
关键字,JDK 10+) - 文本块(
"""
,JDK 13+) - 密封类(
sealed
,JDK 17+) - 记录类(
record
,JDK 16+)
- 局部变量类型推断(
- Lambda 表达式和 Stream API 的增强可能需要代码调整
4. 工具和构建系统
- 升级构建工具版本:
- Maven 需 3.6.0+,推荐 3.8.x
- Gradle 需 6.8+,推荐 7.x
- 调整编译器插件和目标版本(
--release 17
) - 升级 IDE 至支持 JDK 17 的版本(如 IntelliJ IDEA 2021.2+,Eclipse 2021-09+)
5. 性能和 GC 变化
- 默认 GC 变化:JDK 11 后默认使用 G1 GC,JDK 17 引入 ZGC 和 Shenandoah 作为实验性选项
- 可能需要重新评估 GC 参数,特别是从 CMS 迁移到 G1 或 ZGC 时
- 调整内存配置,元空间(Metaspace)参数与永久代不同
6. 安全增强
- 更强的默认安全设置:
- TLS 协议版本默认升级
- 一些加密算法被禁用或限制
- 模块化带来的安全边界增强
- 需检查自定义安全策略和证书管理代码
7. 第三方库兼容性
- 升级所有依赖库至支持 JDK 17 的版本
- 特别注意:
- 字节码操作库(如 ASM、CGLIB)
- ORM 框架(如 Hibernate 需 5.6+)
- 日志框架(如 Log4j 2.17 + 修复安全问题)
- 反射工具类可能需要调整
8. 部署变化
- JRE 不再单独提供,需使用
jlink
创建自定义运行时镜像 - 打包工具变化:
jpackage
(JDK 14+)可用于创建原生安装包 - 容器化部署需调整基础镜像(如使用 openjdk:17-jdk-slim)
升级建议步骤
- 先升级到 JDK 11,解决大部分兼容性问题
- 逐步升级到 JDK 17,利用
--enable-preview
尝试新特性 - 使用
jdeps
工具分析依赖和兼容性问题 - 运行
junit
测试时启用--illegal-access=warn
检测非法访问 - 考虑使用 IDE 的代码迁移工具自动处理部分语法转换
升级过程中,建议建立详细的测试矩阵,确保所有功能在新 JDK 下正常工作,特别是涉及低级别 API 和反射的代码。