百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

保姆级升级 java17 指南,建议收藏

mhr18 2025-01-07 14:20 18 浏览 0 评论

一、前言

Java 17,一个长期支持 (LTS) 版本已经发布半个多月。 不幸的是,许多应用程序仍在旧版本的 Java 上运行,例如以前的 LTS 版本:Java 8 和 Java 11。本文解释了你应该升级应用程序的原因,并帮助你实际升级到 Java 17。

但首先,许多人都可能会问:“为什么要升级?”

  • java9 紧凑字符串(更加节省内存)
  • java11 httpclient
  • java12 switch 表达式(简化代码)
  • java13 多行文本
  • java14 record,匹配模式(简化代码)
  • 等等...

随着 Java 版本迭代,GC 得到大量优化,相对于老版本更快并且节省内存。仅仅靠升级 Java 版本就可以为我们带来众多收益。


二、在 Java 升级期间需要更改什么?

你的应用程序包含你和你的团队编写的代码,并且可能还包含依赖项。 如果从 JDK 中删除了某些内容,则可能会破坏代码、依赖项或两者。 通常有助于确保这些依赖项是最新的,以解决这些问题。 有时,你可能需要等到框架发布与最新 Java 版本兼容的新版本,然后才能开始升级过程。 这意味着作为升级前评估过程的一部分,你对你使用的依赖项需要有很好的了解。

大多数功能不会一次性从 JDK 中全部删除。 首先,功能被标记为弃用。 例如,用于 XML 绑定的 Java 架构 (JAXB) 在 Java 9 中被标记为弃用,然后在 Java 11 中才被删除。如果你一直在更新,那么你会知道弃用,并且你可以在功能被删除之前解决这些问题。 但是,如果你直接从 Java 8 跳到 Java 17,那么可能会踩到很多坑。

要查看 API 更改,例如,查看特定 Java 版本中哪些方法被删除或添加到 String API 中,请查看 Marc Hoffmann 和 Cay Horstmann 撰写的 The Java Version Almanac。


三、多版本 JAR 功能

如果你的基础组件任然被使用在旧的 JDK并且在他们的站点上升级不受你的控制怎么办? Java 9 和 JEP 238 中引入的多版本 JAR 功能可能很有用,因为它允许你将多个 Java 版本(包括早于 Java 9 的版本)的代码打包在一个 JAR 文件中。

例如:创建一个 Application 类(清单 1)和一个 Student 类(清单 2)并将它们放在文件夹 src/main/java/com/example 中,Student 类在 Java 8 上运行。

清单 1. Application class

public class Application {

   public static void main(String[] args) {
       Student student = new Student("James ");
       System.out.println("Implementation " + student.implementation());
       System.out.println("Student name James contains a blank: " + student.isBlankName());
   }
}

清单 2. Student class for Java 8

public class Student {
   final private String firstName;

   public Student(String firstName) {
       this.firstName = firstName;
   }

   boolean isBlankName() {
       return firstName == null || firstName.trim().isEmpty();
   }

   static String implementation() { return "class"; }
}

接下来,创建一个 Student record(清单 3),它不仅使用了 record(Java 14 中引入)而且还使用了 String.isBlank() 方法(Java 11 中引入),并将其放在 src/main/java17/com/example 文件夹。

清单 3. 使用新语法的 Student record

public record Student(String firstName) {
   boolean isBlankName() {
       return firstName.isBlank();
   }

   static String implementation() { return "record"; }
}

根据你使用的构建工具,需要一些配置。 Maven 示例可以在我的 GitHub repository 中找到。 该示例基于 Java 17 构建并创建 JAR 文件。 在 JDK 17 或更高版本上执行 JAR 文件时,将使用学生记录。 在旧版本上执行 JAR 文件时,将使用 Student 类。

当然你也可以参考 https://github.com/xkcoding/simple-http(译者注),我给它 pr 了 java11 下的 HttpClient 支持,该工具使用 Java8 编译。

此功能非常有用,例如,如果新 API 提供更好的性能,因为你可以为拥有最新 Java 版本的客户使用这些 API。 相同的 JAR 文件可用于使用较旧 JDK 的客户,而不会提高性能。

请注意,所有实现(在本例中为 Student)都应具有相同的公共 API 以防止运行时问题。 不幸的是,构建工具不会验证公共 API,但一些 IDE 会验证。 另外,在 JDK 17 中,你可以使用 jar –validate 命令来验证 JAR 文件。

需要注意的是某些版本的 JDK 中存在预览功能。 一些更大的特性首先作为预览发布,并且可能会在下一个 JDK 之一中产生最终特性。 这些预览功能同时存在于 Java 的 LTS 和非 LTS 版本中。 这些功能使用 enable-preview标志启用,默认情况下关闭。 如果你在生产代码中使用这些预览功能,请注意它们可能会在 JDK 版本之间发生变化,这可能会导致需要将代码进行一些调试或重构。


四、有关 Java 弃用和删除的功能

在升级 JDK 之前,请确保你的 IDE、构建工具和依赖项是最新的。Maven Versions Plugin 和 Gradle Versions Plugin 显示你拥有哪些依赖项并列出最新的可用版本。

请注意,这些工具仅显示你使用的依赖的新版本——但有时依赖的名称会发生变化、分叉或代码移动。 例如:JAXB 最初是通过 javax.xml.bind:jaxb-api 提供的,但在它过渡到 Eclipse Foundation 后更改为 jakarta.xml.bind:jakarta.xml.bind-api。 要查找此类更改,你可以使用 Jonathan Lermitage 的 Old GroupIds Alerter plugin for Maven 或他的 plugin for Gradle。

JavaFX. 从 Java 11 开始,不再包含 JavaFX 作为规范的一部分,并且大多数 JDK 版本已将其删除。 你可以使用来自 Gluon 的单独构建的 JavaFX 或将 OpenJFX 依赖项添加到你的项目。

Fonts. 曾几何时,JDK 包含一些字体,但从 Java 11 开始,它们被删除了。 例如:如果你使用 Apache POI(Microsoft Office 兼容文档的 Java API),你将需要字体。 操作系统需要提供字体,因为它们不再存在于 JDK 中。 但是,在 Alpine Linux 等操作系统上,必须使用 apt install fontconfig 命令手动安装字体。 根据你使用的字体,可能需要额外的包。

Java Mission Control. 这是一个非常有用的工具,用于监视和分析你的应用程序。 强烈建议你了解一下。 Java Mission Control 曾经包含在 JDK 中,但现在改了名并且需要单独下载:JDK Mission Control。

Java EE. JDK 11 中最大的变化是删除了 Java EE 模块。 许多应用程序都依赖 Java EE 模块,例如:前面提到的 JAXB。 由于这些模块不再存在于 JDK 中,因此你需要添加相关的依赖项。表格 1 列出了各种模块及其依赖项。 请注意,JAXB 和 JAX-WS 都需要两个依赖项:一个用于 API,另一个用于实现。 另一个变化是命名约定,因为 Java EE 由 Eclipse 基金会以 Jakarta EE 的名义进行维护。 你的包导入可能需要调整,较新版本的 Jakarta EE 使用 jakarta.xml.bind.* 而不是 javax.xml.bind.*。

表格 1. Java EE 模块和当前的替代品

CORBA. Java 的 CORBA 模块没有官方替代品,该模块在 Java 11 中被删除。但是 Oracle GlassFish Server 包含了 CORBA 的实现。

Nashorn. Java 15 删除了 Nashorn JavaScript 引擎。 如果仍想使用它,你可以添加 nashorn-core 依赖。

<dependency>
    <groupId>org.openjdk.nashorn</groupId>
    <artifactId>nashorn-core</artifactId>
    <version>15.3</version>
</dependency>

Experimental compilers. Java 17 删除了对 GraalVM 的实验性提前 (AOT) 和即时 (JIT) 编译器的支持,详见 JEP 410。


五、寻找不受支持的文件

你可能会遇到 Unsupported class file major version 61 这样的错误。我已经在 JaCoCo 代码覆盖库和各种其他 Maven 插件中看到了它。 消息中版本 61 指的是 Java 17。因此,在这种情况下,这意味着你使用的框架或工具的版本不支持 Java 17。因此,你应该将框架或工具升级到 新版本。


六、JDK 内部 API

Java 16 和 Java 17 封装了 JDK 内部 API,这会影响 Lombok 等各种框架。 你可能会看到诸如 module jdk.compiler does not export com.sun.tools.javac.processing to unnamed module,这意味着你的应用程序无法再访问 JDK 的这些内部 API。

通常,我建议升级所有使用这些内部结构的依赖项,并确保你自己的代码不再使用 JDK 的内部 API。

如果这是不可能的,有一个变通方法仍然使你的应用程序能够访问内部。 例如,如果你需要访问 comp 模块,请使用以下命令:

--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED

但是,这只是解决问题的最后手段,最好还是停止使用这些内部 API,因为你正在绕过 Java 团队添加的重要保护措施。

关于此问题更多详细信息可查看 Java 16 的 JEP 396 和 Java 17 的 JEP 403。


七、结论

升级依赖项和为 JDK 已经删除的功能找到替代方案就可以避免大部问题。 我推荐一种结构化的方法来逐步升级:首先,确保代码可以编译,然后运行测试,然后运行应用程序。

如果你可以告诉自己、你的团队和你的公司,你可以在 JDK 17 上编译和测试所有内容,而不必告诉他们几乎已经完成,或者更糟糕的是,它只完成了 80%,那么迁移过程就会好得多。

我希望这篇文章能够对你有所作用,能帮助你平稳升级到 Java17。


八、译者说

笔者开源的微服务组件 mica 已经适配 java17,mybatis-plus 新版也已经支持。目前笔者已经有一部分服务升级到 Java17,很丝滑,如果你有升级 Java 的想法,不妨直接升级到 Java17。关注我,学习技术不迷路!

相关推荐

【预警通报】关于WebLogic存在远程代码执行高危漏洞的预警通报

近日,Oracle官方发布了2021年1月关键补丁更新公告CPU(CriticalPatchUpdate),共修复了包括CVE-2021-2109(WeblogicServer远程代码执行漏洞)...

医院信息系统突发应急演练记录(医院信息化应急演练)

信息系统突发事件应急预案演练记录演练内容信息系统突发事件应急预案演练参与人员信息科参与科室:全院各部门日期xxxx-xx-xx时间20:00至24:00地点信息科记录:xxx1、...

一文掌握怎么利用Shell+Python实现完美版的多数据源备份程序

简介:在当今数字化时代,无论是企业还是个人,数据的安全性和业务的连续性都是至关重要的。数据一旦丢失,可能会造成无法估量的损失。因此,如何有效地对分布在不同位置的数据进行备份,尤其是异地备份,成为了一个...

docker搭建系统环境(docker搭建centos)

Docker安装(CentOS7)1.卸载旧版Docker#检查已安装版本yumlistinstalled|grepdocker#卸载旧版本yumremove-ydocker.x...

基础篇:数据库 SQL 入门教程(sql数据库入门书籍推荐)

SQL介绍什么是SQLSQL指结构化查询语言,是用于访问和处理数据库的标准的计算机语言。它使我们有能力访问数据库,可与多种数据库程序协同工作,如MSAccess、DB2、Informix、M...

Java21杀手级新特性!3行代码性能翻倍

导语某券商系统用这招,交易延迟从12ms降到0.8ms!本文揭秘Oracle官方未公开的Record模式匹配+虚拟线程深度优化+向量API神操作,代码量直降70%!一、Record模式匹配(代码量↓8...

一文读懂JDK21的虚拟线程(java虚拟线程)

概述JDK21已于2023年9月19日发布,作为Oracle标准Java实现的一个LTS版本发布,发布了15想新特性,其中虚拟线程呼声较高。虚拟线程是JDK21中引入的一项重要特性,它是一种轻量级的...

效率!MacOS下超级好用的Linux虚拟工具:Lima

对于MacOS用户来说,搭建Linux虚拟环境一直是件让人头疼的事。无论是VirtualBox还是商业的VMware,都显得过于笨重且配置复杂。今天,我们要介绍一个轻巧方便的纯命令行Linux虚拟工具...

所谓SaaS(所谓三维目标一般都应包括)

2010年前后,一个科技媒体的主编写一些关于云计算的概念性问题,就可以作为头版头条了。那时候的云计算,更多的还停留在一些概念性的问题上。而基于云计算而生的SaaS更是“养在深闺人未识”,一度成为被IT...

ORA-00600 「25027」 「x」报错(报错0xc0000001)

问题现象:在用到LOB大对象的业务中,进行数据的插入,失败了,在报警文件中报错:ORA-00600:内部错误代码,参数:[25027],[10],[0],[],[],[],[],[...

安卓7源码编译(安卓源码编译环境lunch失败,uname命令找不到)

前面已经下载好源码了,接下来是下载手机对应的二进制驱动执行编译源码命令下载厂商驱动https://developers.google.com/android/drivers?hl=zh-cn搜索NGI...

编译安卓源码(编译安卓源码 电脑配置)

前面已经下载好源码了,接下来是下载手机对应的二进制驱动执行编译源码命令下载厂商驱动https://developers.google.com/android/drivers?hl=zh-cn搜索NGI...

360 Vulcan Team首战告捷 以17.5万美金强势领跑2019“天府杯“

2019年11月16日,由360集团、百度、腾讯、阿里巴巴、清华大学与中科院等多家企业和研究机构在成都联合主办了2019“天府杯”国际网络安全大赛暨2019天府国际网络安全高峰论坛。而开幕当日最激荡人...

Syslog 日志分析与异常检测技巧(syslog发送日志配置)

系统日志包含有助于分析网络设备整体运行状况的重要信息。然而,理解并从中提取有效数据往往颇具挑战。本文将详解从基础命令行工具到专业日志管理软件的全流程分析技巧,助你高效挖掘Syslog日志价值。Gr...

从Oracle演进看数据库技术的发展(从oracle演进看数据库技术的发展的过程)

数据库技术发展本质上是应用需求驱动与基础架构演进的双向奔赴,如何分析其技术发展的脉络和方向?考虑到oracle数据库仍然是这个领域的王者,以其为例,管中窥豹,对其从Oracle8i到23ai版本的核...

取消回复欢迎 发表评论: