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

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

mhr18 2025-01-07 14:20 12 浏览 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。关注我,学习技术不迷路!

相关推荐

使用 Docker 部署 Java 项目(通俗易懂)

前言:搜索镜像的网站(推荐):DockerDocs1、下载与配置Docker1.1docker下载(这里使用的是Ubuntu,Centos命令可能有不同)以下命令,默认不是root用户操作,...

Spring Boot 3.3.5 + CRaC:从冷启动到秒级响应的架构实践与踩坑实录

去年,我们团队负责的电商订单系统因扩容需求需在10分钟内启动200个Pod实例。当运维组按下扩容按钮时,传统SpringBoot应用的冷启动耗时(平均8.7秒)直接导致流量洪峰期出现30%的请求超时...

《github精选系列》——SpringBoot 全家桶

1简单总结1SpringBoot全家桶简介2项目简介3子项目列表4环境5运行6后续计划7问题反馈gitee地址:https://gitee.com/yidao620/springbo...

Nacos简介—1.Nacos使用简介

大纲1.Nacos的在服务注册中心+配置中心中的应用2.Nacos2.x最新版本下载与目录结构3.Nacos2.x的数据库存储与日志存储4.Nacos2.x服务端的startup.sh启动脚...

spring-ai ollama小试牛刀

序本文主要展示下spring-aiollama的使用示例pom.xml<dependency><groupId>org.springframework.ai<...

SpringCloud系列——10Spring Cloud Gateway网关

学习目标Gateway是什么?它有什么作用?Gateway中的断言使用Gateway中的过滤器使用Gateway中的路由使用第1章网关1.1网关的概念简单来说,网关就是一个网络连接到另外一个网络的...

Spring Boot 自动装配原理剖析

前言在这瞬息万变的技术领域,比了解技术的使用方法更重要的是了解其原理及应用背景。以往我们使用SpringMVC来构建一个项目需要很多基础操作:添加很多jar,配置web.xml,配置Spr...

疯了!Spring 再官宣惊天大漏洞

Spring官宣高危漏洞大家好,我是栈长。前几天爆出来的Spring漏洞,刚修复完又来?今天愚人节来了,这是和大家开玩笑吗?不是的,我也是猝不及防!这个玩笑也开的太大了!!你之前看到的这个漏洞已...

「架构师必备」基于SpringCloud的SaaS型微服务脚手架

简介基于SpringCloud(Hoxton.SR1)+SpringBoot(2.2.4.RELEASE)的SaaS型微服务脚手架,具备用户管理、资源权限管理、网关统一鉴权、Xss防跨站攻击、...

SpringCloud分布式框架&amp;分布式事务&amp;分布式锁

总结本文承接上一篇SpringCloud分布式框架实践之后,进一步实践分布式事务与分布式锁,其中分布式事务主要是基于Seata的AT模式进行强一致性,基于RocketMQ事务消息进行最终一致性,分布式...

SpringBoot全家桶:23篇博客加23个可运行项目让你对它了如指掌

SpringBoot现在已经成为Java开发领域的一颗璀璨明珠,它本身是包容万象的,可以跟各种技术集成。本项目对目前Web开发中常用的各个技术,通过和SpringBoot的集成,并且对各种技术通...

开发好物推荐12之分布式锁redisson-sb

前言springboot开发现在基本都是分布式环境,分布式环境下分布式锁的使用必不可少,主流分布式锁主要包括数据库锁,redis锁,还有zookepper实现的分布式锁,其中最实用的还是Redis分...

拥抱Kubernetes,再见了Spring Cloud

相信很多开发者在熟悉微服务工作后,才发现:以为用SpringCloud已经成功打造了微服务架构帝国,殊不知引入了k8s后,却和CloudNative的生态发展脱轨。从2013年的...

Zabbix/J监控框架和Spring框架的整合方法

Zabbix/J是一个Java版本的系统监控框架,它可以完美地兼容于Zabbix监控系统,使得开发、运维等技术人员能够对整个业务系统的基础设施、应用软件/中间件和业务逻辑进行全方位的分层监控。Spri...

SpringBoot+JWT+Shiro+Mybatis实现Restful快速开发后端脚手架

作者:lywJee来源:cnblogs.com/lywJ/p/11252064.html一、背景前后端分离已经成为互联网项目开发标准,它会为以后的大型分布式架构打下基础。SpringBoot使编码配置...

取消回复欢迎 发表评论: