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

是时候用Java 17了(我的世界java版下载)

mhr18 2024-09-17 23:24 14 浏览 0 评论

关于从先前的长期支持版本(Java 11 和 Java 8)迁移代码,需要知道的是什么?
整理 | 王晓曼
出品 | CSDN(ID:CSDNnews)

Spring Framework 6 将采用 Java 17 和 Jakarta EE 9

正如在 SpringOne 上宣布的那样,Spring Framework 6 和Spring Boot 3 计划在 2022 年第四季度实现总体可用性的高端基线:
  • Java 17+(来自 Spring Framework 5.3.x 线中的 Java 8-17)
  • Jakarta EE 9+(来自Spring框架5.3.x 线中的 Java EE 7-8)
这一前瞻性的基线将为我们的 APl 设计和集成工作带来巨大的好处,在未来的许多年里,它将为应用程序代码和框架以及应用程序带来光明。然而,这当然是有代价的:Spring Framework 6 和 Spring Boot 3 的应用程序在运行时至少需要 JDK 17,以及 Tomcat 10 /Jetty 11(为了兼容 Jakarta EE 9)。更重要的是,在你的应用程序源代码中可能需要一些更改:例如在 jakarta EE 9 中 javax 到 jakarta 命名空间的更改,无论你在哪里接触 Servlet API、JPA、Bean Validation 等。
虽然一开始这听起来有点咄咄逼人,但请记住,我们谈论的是2022年第四季度的发布:届时,不仅 JDK 17 将取代 JDK 11 成为下一个长期支持版本,而且它本身也将被 JDK 18 和 JDK 19 作为当时可用的特性版本取代,而 JDK 20 的特性已经接近冻结。
Jakarta EB 9 也一样:我们预计届时 Jakarta EE 10 将会推出,而另一代 Tomcat、Jetty 和 co 将作为运行时选项被支持。保持以上基线作为最小值,这允许在 Spring Framework 6.x 中进一步了解 Java 的发展,Java 17 和 Jakarta EE 9 只是开始。
同时,Spring Framework 5.3.x 和 Spring Boot 2.x 目前仍在积极开发中,今年 11 月将推出 Spring Boot 2.6,然后在 2022 年 5 月推出 Spring Boot 2.7,最新一次 Spring Boot 2.x 特性分支已经到达(还没有确定这是 2.7 还是可能的更高版本),该分支将与 Spring Framework 5.3 一起进入扩展的开源维护阶段。与 Spring Framework 6 和 Spring Boot 3 并行,有好几年的重叠。考虑我们之前对 Spring Framework 3.2.x 和4.3.x 的分支,以了解在实践中将如何实现。
因此,如果你打算继续使用 JDK 8 或 11 几年,或者即使你打算继续使用 JDK17上的 Spring Framework 5.3 基础设施几年,请放心,我们对 Spring Framework 5.3.x 和 Spring Boot 2.x 的扩展维护是可以的,会让你覆盖。
一旦你准备使用下一代应用程序的 Java 生态系统,以自己的节奏随时升级到 Spring 框架 6 和 Spring Boot 3,随着 Tomcat、Jetty 和 co——新基础设施的好处和新建筑成为可用的选项。我们希望在接下来的几年里你们会欣赏这些选择。
注:如果你想知道 JDK 11 作为一个 LTS 的生成,请注意,JDK 11 的商业支持时间框架比 JDK 8 短,JDK 11 的 LTS 将在 2023 年底淘汰。JDK 17 作为下一代 LTS 将提供至少到 2026 年的支持时间框架。我们认为 JDK 8 在生态系统中具有独特的作用;
相比之下,JDK 11 只是一个过渡版本。此外,JDK 17 提供了一组最近积累起来的语言、API 和 JVM 增强功能,使其成为一个更有吸引力的升级。同样重要的是,在同一个 Spring Framework 6.x 中,JDK 23 LTS(2024年)和 JDK 29 LTS(2027年)仍然会支持,最终的支持范围会更广 JDK 17-29。

为什么要升级到 Java 17?

Java 17, Java 语言和运行平台的下一个长期支持(LTS)版本,将于 9 月 14 日正式发布。不幸的是,许多应用程序仍然在旧版本的 Java 上运行,比如以前的 LTS 版本:Java 11 和 Java 8。本文解释了为什么应该升级应用程序,并帮助您实际升级到Java 17。
但首先,你们很多人可能会问:“为什么升级?”
为什么会有人想要升级到最新的 Java 版本?特别是如果你的应用程序在 Java 8、Java 11、Java 14 或您正在使用的任何版本上运行得很好时,这是有理由怀疑的。升级到 Java 17 需要付出努力,尤其是对那些目标是真正利用 JVM 中的新语言特性和功能的人。
没错,根据环境和应用程序的不同,可能需要进行一些升级。开发人员和其他团队成员需要更新他们的本地环境。此外,构建环境和运行环境(如生产环境)也需要升级。
幸运的是,许多项目和团队使用 Docker,它在这方面帮助很大。在我自己的团队中,团队定义了他们自己的持续集成/持续部署(CI/CD)管道,他们用 Docker 映像运行一切。团队可以通过在他们的 Docker 映像中指定该版本升级到最新的 Java 版本——这不会影响其他可能在旧 Java 版本上运行的团队,因为这些团队使用的是旧的 Docker 映像。
在 Kubernetes 上运行的测试和生产环境也是如此。当一个团队想要升级到一个新的 Java 版本时,他们可以自己更改 Docker 映像,然后部署所有内容。(当然,如果您仍然有共享的构建环境,或者其他管理您环境的团队,这个过程可能会有点挑战性。)
应用程序也可能需要做一些更改。我注意到,团队发现有这么多的工作量是很有挑战性的,以致将一个应用程序从 Java 8 升级到 Java 11 需要几周甚至几个月的时间。过高的估计往往会导致公司因为其他优先事项而推迟升级。
我试图升级了一个应用程序,估计需要几周时间,但实际只花了几天时间,主要是因为等待构建的完成。这部分是由于多年的升级经验,但这也是一个刚刚起步的问题,并试图在过程中解决问题。这是一个周五下午的好工作内容;看看你已经完成了多少工作,还有哪些挑战,这样就更容易估算剩下的工作。
然而,即使有多年的经验,在没有关于项目深入信息的情况下,我也无法估计升级需要多长时间。这很大程度上取决于应用程序有多少依赖项。通常,将依赖项升级到最新版本可以解决 Java 升级过程中可能出现的许多问题。

LTS 版本

本文一直引用 Java 8、Java 11 和 Java 17 作为 LTS 版本。这是什么意思?下面是对 Oracle Java SE 支持路线图的引用:
对于 Java SE 8 之后的产品版本,Oracle 将每三年指定一个版本作为长期支持的(LTS)版本。Java SE 11 是一个 LTS 版本。出于 Oracle Premier Support 的目的,非 LTS 版本被认为是最新 LTS 版本的累积实现增强集。
一旦一个新的特性版本可用,任何以前的非 LTS 版本都将被认为是可取代的。例如,Java SE 9 是一个非 LTS 版本,并立即被 Java SE 10 (也是非 LTS )所取代,而 Java SE 10 又立即被 Java SE 11 所取代。然而,Java SE 11 是一个 LTS 版本,因此,即使 Java SE 12 已经发布,Oracle 客户也将收到 Oracle Premier 支持和定期更新的版本。

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

你的应用程序包含你和你的团队编写的代码,它可能还包含依赖项。如果从 JDK 中删除了某些内容,可能会破坏代码、依赖关系,或者两者都破坏。这通常有助于确保这些依赖项是最新的,以解决这些问题。有时,在开始升级过程之前,你可能必须等待框架发布与最新 Java 版本兼容的新版本。
这意味着,作为升级前评估过程的一部分,您对依赖项要有很好的了解。
大多数功能不会一下子从 JDK 中全部删除。首先,功能被标记为弃用。例如,用于 XML 绑定的 Java 体系结构(JAXB)在 Java 9 中被标记为弃用,然后在Java 11 中被删除。如果您不断更新,则会看到被弃用的部分,并且可以在功能被删除前解决这些特性的任何使用问题。但是,如果直接从 Java 8 跳到 Java 17,那么这个特性的删除将会立刻给您造成影响。
要查看 API 的变化,例如,查看在特定的 Java 版本中哪些方法被删除或添加到 String APl 中,可以查看 Marc Hoffmann 和 Cay Horstmann 的 Java 版本年鉴,或者 Foojay 的 Java 版本年鉴。

Multirelease JAR 功能

如果你的应用程序被仍然使用旧 JDK 的客户使用,并且站点的升级不在你的控制范围内,该怎么办?在 Java 9 和 JEP 238 中引入的多版本 JAR 功能可能很有用,因为它允许将多个 Java 版本(包括比 Java 9更老的版本)的代码打包到一个 JAR 文件中。
例如,创建一个 Application 类(清单1)和一个 Student 类(清单2),并将它们放在 src/main/java/com/example 文件夹中。Student 类是一个在 Java 8 上运行的类。
清单1:应用程序类
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:为 Java 8 编写的 Student 类:
public class Student {final private String firstName;public Student(String firstName) {this.firstName = firstName; }boolean isBlankName() {return firstName == || firstName.trim().isEmpty(); }static String implementation() { return "class"; }}
接下来,创建一个 Student 记录(清单3),它不仅使用记录(在 Java 14 中引入),还使用 String.isBlank() 方法(在 Java 11 中引入),并将其放在文件夹 src/main/java17/com/example 中。
清单3:使用较新 Java 特性的 Student 记录
public record Student(String firstName) {boolean isBlankName() {return firstName.isBlank(); }static String implementation() { return "record"; }}
需要一些配置,但这是取决于你使用的构建工具。可以在我的 GitHub 存储库中找到一个 Maven 示例。该示例构建在 Java 17 上,并创建 JAR 文件。当在 JDK 17 或更新版本上执行 JAR 文件时,将使用 Student 记录。在旧版本上执行 JAR 文件时,将使用 Student 类。
这个特性是非常有用的,例如,如果新的 API 提供更好的性能,因为你可以使用那些有最新 Java 版本的客户的 API 。使用旧 JDK 的客户可以使用相同的 JAR 文件,而不需要提高性能。
请注意,在本示例中,所有的实现,即 Student,都应该具有相同的公共 API,以防止出现运行问题。但是,构建工具不验证公共 API,但一些 IDE 可以。此外,在 JDK 17 中,你可以使用 jar -validate 命令来验证 JRA 文件。
需要注意的是,JDK 某些版本中提供的预览功能。一些较大的特性首先以预览的形式发布,可能会在下一个 JDK 中形成最终的特性。这些预览特性在 Java 的 LTS 和非 LTS 版本中都有,并且,这些特性是通过 enable-preview 标志启用的,默认情况下是关闭的。如果你在产品代码中使用这些预览特性,请注意它们可能会在 JDK 版本之间发生变化,这可能会导致需要进行一些调试或重构。

关于 Java 弃用和特性移除的更多信息

在升级 JDK 之前,请确保你的 IDE、构建工具和依赖项是最新的。Maven 版本插件和 Gradle 版本插件会显示你有哪些依赖项,并列出最新的可用版本。
请注意,这些工具只显示您所使用文件的新版本——但有时文件名称会更改,会产生分叉,或者代码会移动。例如,JAXB 首先是通过 jakarta.xml.bind: jaxb-api,但改为 jakarta.xml.bind: jakarta.xml.bindapi 在它过渡到 Eclipse Foundation 之后。要找到这样的变化,你可以使用 Jonathan Lermitage 的 Maven Old Grouplds Alerter 插件或者它的 Gradle 插件。
JavaFX从 Java 11 开始,平台不再将 JavaFX 作为规范的一部分,大多数 JDK 构建已经删除了它。你可以使用来自 Gluon 的独立 JavaFX 构建,或者将 OpenJFX 依赖项添加到你的项目中。
字体曾经 JDK 包含一些字体,但是从 Java 11 开始,它们被删除了。例如,如果你使用 Apache POI(用于 Microsoft Office 兼容文档的 Java API)。你需要字体,操作系统需要提供字体,因为它们不再出现在 JDK 中。但是,在诸如 Alpine Linux 这样的操作系统中,字体必须使用 apt install fontconfigcommand 手动安装,根据您使用的字体,可能需要额外的字体包。
Java 任务控制。对于监视和分析应用程序,这是一个非常有用的工具。我强烈建议你调查一下。Java Mission Control 曾经包含在 JDK 中,但现在它可以作为一个单独的下载,并以新的名称提供:JDK Mission Control。
Java EE。JDK 11 中最大的变化是删除了 Java EE 模块。前面提到的 JAXB 等 Java EE 模块被许多应用程序使用。既然这些模块不再存在于 JDK 中,你应该添加相关的依赖项。表 1 列出了各种模块及其依赖关系。
请注意,JAXB 和 JAX-WS 都需要两个依赖项:一个用于 API,另一个用于实现。另一个变化是命名约定,现在 Java EE 由 Eclipse Foundation 以 Jakarta EE 的名称维护。你的包导入需要反映这种变化,例如 jakarta.xml。绑定。应该使用 * 而不是 javax.xml.bind。
表1:Java EE 模块及其当前替换
CORBA。Java 的 CORBA 模块没有正式的替代,它在 Java 11 中被删除了。然而,Oracle GlassFish Server 包含 CORBA 的实现。
Nashorn。Java 15 删除了 Nashorn JavaScript 引擎。如果你仍然想使用引擎,您可以使用 nashorncore 依赖项。
实验的编译器。Java 17 删除了对 GraalVM 实验性的提前(AOT)和即时(JIT)编译器的支持,这在 JEP 410 的文档中有解释。

注意不支持的主文件

你可能会看到错误:Unsupported class file major version 61。我 在JaCoCo 代码覆盖库和各种其他 Maven 插件中看到过它。消息的主要版本 61指的是 Java 17。在这种情况下,这意味着你使用的框架或工具的版本不支持 Java 17。因此,你应该将框架或工具升级到新版本。(如果你看到一条包含主版本 60 的消息,那么它与 Java 16 有关。)
请注意,一些工具,如 Kotlin 和 Gradle 还不支持 Java 17,至少在我写这篇文章的时候(2021年8月中旬)是这样的。
有时可以解决这个问题,例如,将 Java 16 指定为 Kotlin 的 JVM 目标。不过,我希望 Java 17 支持很快就会加入。

封装 JDK 内部 API

Java 16 和 Java 17 封装了 JDK 内部 API,这影响了各种框架,比如 Lombok。你可能会看到类似module jdk.compiler 没有导出 com.sun.tools 这样的错误,这意味着你的应用程序不再能够访问 JDK 的那一部分。
总的来说,我建议升级所有使用这些内部组件的依赖项,并确保您自己的代码不再使用它们。
如果这实现不了,有一个解决方案仍然使你的应用程序访问内部。例如,如果你需要访问 comp 模块,请使用以下命令:
——add-opens = jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
但是,只能将此解决方案作为最后的手段,最好是临时使用,因为您正在规避 Java 团队添加的重要保护措施。
了解关于 JEP 396 中的 Java 16 和 JEP 403 中的 Java 17 的更多信息。

Java升级资源

建议查看我创建的 JavaUpgrades GitHub 存储库,其中包含一些示例、常见错误和解决方案,可以在升级过程中帮助你。

结论

升级依赖关系并为已删除的 JDK 特性添加依赖关系可以解决许多 Java 升级挑战。我建议采用一种结构化的方法逐步升级:首先,确保代码已编译,然后运行测试,再运行应用程序。
如果你告诉自己、团队和公司你可以在 JDK 17 上编译和测试所有的东西,而不是告诉他们它几乎已经完成了,或者更糟的是,它只完成了 80%,那么迁移的过程就会容易很多。
我个人的经验是,从 JDK 11 升级到 JDK 17 要比从 JDK 8 升级到 JDK 11 容易得多。然而,在这两种情况下,对于重要的应用程序来说都是几个小时到几天的时间不等,这主要是由于等待构建完成。
希望本文能简化的升级过程。
参考链接:
https://spring.io/blog/2021/09/02/a-java-17-and-jakarta-ee-9-baseline-for-spring-framework-6
https://blogs.oracle.com/javamagazine/migrate-to-java-17

相关推荐

B站收藏视频失效?mybili 收藏夹备份神器完整部署指南

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:羊刀仙很多B站用户都有过类似经历:自己精心收藏的视频突然“消失”,点开一看不是“已被删除”,就是“因UP主设置不可见”。而B站并不会主动通知...

中间件推荐初始化配置

Redis推荐初始化配置bind0.0.0.0protected-modeyesport6379tcp-backlog511timeout300tcp-keepalive300...

Redis中缓存穿透问题与解决方法

缓存穿透问题概述在Redis作为缓存使用时,缓存穿透是常见问题。正常查询流程是先从Redis缓存获取数据,若有则直接使用;若没有则去数据库查询,查到后存入缓存。但当请求的数据在缓存和数据库中都...

后端开发必看!Redis 哨兵机制如何保障系统高可用?

你是否曾在项目中遇到过Redis主服务器突然宕机,导致整个业务系统出现数据读取异常、响应延迟甚至服务中断的情况?面对这样的突发状况,作为互联网大厂的后端开发人员,如何快速恢复服务、保障系统的高可用...

Redis合集-大Key处理建议

以下是Redis大Key问题的全流程解决方案,涵盖检测、处理、优化及预防策略,结合代码示例和最佳实践:一、大Key的定义与风险1.大Key判定标准数据类型大Key阈值风险场景S...

深入解析跳跃表:Redis里的"老六"数据结构,专治各种不服

大家好,我是你们的码农段子手,今天要给大家讲一个Redis世界里最会"跳科目三"的数据结构——跳跃表(SkipList)。这货表面上是个青铜,实际上是个王者,连红黑树见了都要喊声大哥。...

Redis 中 AOF 持久化技术原理全解析,看完你就懂了!

你在使用Redis的过程中,有没有担心过数据丢失的问题?尤其是在服务器突然宕机、意外断电等情况发生时,那些还没来得及持久化的数据,是不是让你夜不能寐?别担心,Redis的AOF持久化技术就是...

Redis合集-必备的几款运维工具

Redis在应用Redis时,经常会面临的运维工作,包括Redis的运行状态监控,数据迁移,主从集群、切片集群的部署和运维。接下来,从这三个方面,介绍一些工具。先来学习下监控Redis实时...

别再纠结线程池大小 + 线程数量了,没有固定公式的!

我们在百度上能很轻易地搜索到以下线程池设置大小的理论:在一台服务器上我们按照以下设置CPU密集型的程序-核心数+1I/O密集型的程序-核心数*2你不会真的按照这个理论来设置线程池的...

网络编程—IO多路复用详解

假如你想了解IO多路复用,那本文或许可以帮助你本文的最大目的就是想要把select、epoll在执行过程中干了什么叙述出来,所以具体的代码不会涉及,毕竟不同语言的接口有所区别。基础知识IO多路复用涉及...

5分钟学会C/C++多线程编程进程和线程

前言对线程有基本的理解简单的C++面向过程编程能力创造单个简单的线程。创造单个带参数的线程。如何等待线程结束。创造多个线程,并使用互斥量来防止资源抢占。会使用之后,直接跳到“汇总”,复制模板来用就行...

尽情阅读,技术进阶,详解mmap的原理

1.一句话概括mmapmmap的作用,在应用这一层,是让你把文件的某一段,当作内存一样来访问。将文件映射到物理内存,将进程虚拟空间映射到那块内存。这样,进程不仅能像访问内存一样读写文件,多个进程...

C++11多线程知识点总结

一、多线程的基本概念1、进程与线程的区别和联系进程:进程是一个动态的过程,是一个活动的实体。简单来说,一个应用程序的运行就可以被看做是一个进程;线程:是运行中的实际的任务执行者。可以说,进程中包含了多...

微服务高可用的2个关键技巧,你一定用得上

概述上一篇文章讲了一个朋友公司使用SpringCloud架构遇到问题的一个真实案例,虽然不是什么大的技术问题,但如果对一些东西理解的不深刻,还真会犯一些错误。这篇文章我们来聊聊在微服务架构中,到底如...

Java线程间如何共享与传递数据

1、背景在日常SpringBoot应用或者Java应用开发中,使用多线程编程有很多好处,比如可以同时处理多个任务,提高程序的并发性;可以充分利用计算机的多核处理器,使得程序能够更好地利用计算机的资源,...

取消回复欢迎 发表评论: