你应该采用Java 12还是坚持使用Java 11?

284 阅读10分钟

你应该采用Java 12还是在未来3年内坚持使用Java 11?这似乎是一个无关紧要的问题,但对于那些在JVM上运行的人来说,这却是最重要的决定之一。我将尝试涵盖这个决定的关键方面,并假设你关心在生产中运行最新的安全补丁集。

TL;DR,在采用Java 12之前,充分了解并接受风险是至关重要的。

Java的发行列车

现在每六个月就有一个新的Java版本,所以尽管Java 11刚刚发布,但Java 12还有不到五个月的时间。作为转向更频繁发布的过程的一部分,某些版本被指定为LTS(长期支持),因此将在四年或更长时间内提供安全补丁。这使得它们成为 "主要 "版本,不是因为它们有更大的功能集,而是因为它们有多年的支持。

预计Java 11补丁(11.0.1、11.0.2、11.0.3等)将比Java 8更新(8u20、8u40、8u60等)更小、更简单--Java 11更新将更注重安全补丁,没有Java 8更新的内部增强功能。 相反,甲骨文希望我们把Java 12、13、14等视为小型升级,类似于想象中的Java 11u20、11u40等。 说白了,我觉得这毫无道理。

甲骨文公司的高级员工一再争辩说,8u20和8u40等更新版本经常破坏代码。 这不是我的经验。事实上,我的经验是,更新版本主要包含错误修复。 我所记得的唯一突破是在Javadoc中增加--allow-script-in-comments ,这并不是Java的核心部分。因此,我从来不害怕拿起最新的更新版本--而这一直是Java平台的核心好处。

深入了解为什么更新版本往往不会造成任何问题,让我们来看看不同的版本类型之间的区别。

模式旧模式新模式
升级Java主要版本Java更新版本Java发布培训Java补丁
频率每3年左右一次每6个月一次每6个月一次每3个月一次
版本6 -> 7 -> 88 -> 8u20 -> 8u4011 -> 12 -> 1311 -> 11.0.1 -> 11.0.2
语言变化
JVM的变化
主要改进
增加了类/方法
删除的类/方法
新的弃用
内部改进
JDK工具变更
错误修复
安全补丁

鉴于上述表格,我发现有人会声称从11到12再到13,就像从8u20到8u40。 但这就是Oracle的官方观点。

从Java 9->10->11更接近于从8->8u20->8u40,而不是从7->8->9。
Oracle FAQ

正如该表明确显示的那样,Java发布列车中的每个版本都可能包含传统上与完整的主要版本相关的任何变化。 这些变化包括语言变化和JVM变化,两者都对IDE、字节码库和框架有重大影响。 此外,不仅会有额外的API,还会有API移除(这在8之前是不会发生的)。

甲骨文公司声称,由于每个版本在前一个版本之后只有6个月,所以不会有那么多的 "东西 "在里面,因此升级起来不会那么困难。这虽然是事实,但也是不相关的。重要的是升级是否有可能破坏你的代码栈。很明显,从11->12->13,比8->8u20->8u40的破坏潜力大得多

与8u20->8u40这样的升级相比,关键的区别在于字节码版本的变化和规范的变化。 字节码版本的变化往往特别具有破坏性,大多数框架都大量使用ASM或ByteBuddy这样的库,它们与每个字节码版本紧密相连。而从8u20->8u40仍有相同的Java SE规范,有所有相同的类和方法,这一点从12到13是不能依赖的。我根本不接受甲骨文的论点,即一个版本中 "东西的数量 "比 "东西的类型 "更重要。

他们指出,如果你坚持使用Java 11,并计划在下一个LTS版本发布时转移到它(即Java 17),你可能会发现你的代码不能被编译。记住,现在的Java开发规则规定,一个API方法可以在一个版本中被废弃,而在下一个版本中被删除。这些规则并没有考虑到LTS版本。因此,一个方法可以在13版中被废弃,而在15版中被删除。从11版升级到17版的人将会发现一个被删除的API,因为他们从来没有看到过废止的情况。 不过,我们不要对删除的情况过于恐慌--唯一可能被删除的API是专业的,而不是那些被应用代码广泛使用的。

采用发布列车前的考虑因素

在这一节中,我试图概述一下在采用发布列车之前必须考虑的一些问题/风险。

锁定在火车
如果你采用了Java 12并使用了新的语言特性或新的API,那么你实际上是把你的项目锁定在了发布列车上。 你必须采用Java 13、14、15、16和17。 而且你必须在下一个版本出来的一个月内采用每个新版本

请记住,在新的发布列车上,每个版本的寿命为6个月,发布后7个月就会被淘汰。这是因为每个版本只有6个月的安全补丁,第一个补丁是在发布后1个月,第二个是在发布后4个月。7个月后,下一组安全补丁出来了,但旧版本不会得到这些补丁。

你的程序是否允许在这狭窄的1个月时间内进行Java升级、任何必要的错误修复、测试和发布?或者你愿意在生产中运行低于安全基线的Java版本?

升级障碍
有许多可能的事情会阻碍 Java 的升级。让我们列举一些常见的情况。

开发资源不足。你的团队可能会很忙,或者被裁员,或者项目进入生产阶段,团队被解散。你能保证在两年内有开发时间来完成从Java 15到16的升级吗?

构建工具和IDE。你的IDE会在发布当天支持每个新版本吗?Maven会吗?Gradle?如果他们不支持,你有备份计划吗?记住,你只有1个月的时间来完成升级、测试并将其发布到生产中。 在这一部分,其他工具包括Checkstyle、JaCoCo、PMD、SpotBugs等。

依赖性。你的依赖性是否都能为每个新版本做好准备?足够快的速度让你满足1个月的期限?记住,这不仅仅是你的直接依赖,而是你的堆栈中的一切。例如,字节码操作库尤其受到影响,如ByteBuddy和ASM。

框架。另一种依赖关系,但也是一个庞大而重要的依赖关系。Spring是否会在狭窄的一个月的时间窗口内每六个月产生一个新的版本?Jakarta EE(以前的Java EE)会吗?如果他们不这样做会怎样?

现在,对任何这些障碍的传统做法是等待。对于到8为止的Java版本,通常的做法是在开始升级之前等待6到12个月,以便让工具、库和框架有机会修复任何错误。但当然,等待的方法与发布的列车是不相容的。

云/托管/部署
你能控制你的代码在生产中运行的地点和方式吗?例如,如果你在AWS Lambda中运行你的代码,你就没有控制权。 AWS Lambda没有采用Java 9或10,他们甚至没有Java 11,尽管它已经发布了一个多月。 除非AWS公开保证支持每个新的Java版本,否则你根本无法采用Java 12。(我的工作假设是,AWS Lambda将只支持主要的LTS版本,由Amazon Corretto JDK公告支持)。

你的CI系统的托管情况如何?Jenkins、Travis、Circle、Shippable、GitLab是否会迅速更新?如果它们不能,你会怎么做?

预测未来
也许你已经读完了上面的清单,并且很高兴你今天的代码和流程能够应付。很好!但关键是要明白,你也限制了你在未来改变的能力。

例如,也许你的代码今天不能在AWS Lambda上运行。但你愿意说你在未来三年内都不能这样做吗?

为发布列车做规划

如果你正在考虑采用发布列车,我建议你准备一个清单,列出你现在依赖的所有东西,或者在未来三年可能依赖的东西。 你需要确信清单上的所有东西都能正常工作,并随着发布列车一起升级,或者有一个计划,如果该依赖性不能升级。 我日常工作的清单是这样的。

  • 亚马逊AWS
  • Eclipse
  • IntelliJ
  • Travis CI
  • Shippable CI
  • Maven
  • Maven插件(编译、jar、源代码、javadoc等)
  • Checkstyle,以及相关的IDE插件和maven插件
  • JaCoCo,及相关IDE插件和maven插件
  • PMD,及相关的maven插件
  • SpotBugs,及相关的maven插件
  • OSGi捆绑元数据工具
  • 字节码工具(Byte buddy / ASM等)
  • 100多个jar文件的依赖性

我可能还忘了一些东西。

不要误会我的意思。我认为完全可以做出选择,说你愿意承担风险。 新的语言特性带来的好处,以及可能增强的性能,使得这种努力是值得的。 但我坚信,这比留在Java 11上的风险更大。

中间立场?

一个可能的中间路线是为Java 12开发你的应用程序,但一旦它们出来,就在生产中运行在Java 13、14、15等。 可悲的是,这种方法的可行性比它应该的要低。

API的删除和字节码版本的改变给堆栈增加了不确定性。 即使你的代码不使用被删除的API,你的一个库也可能使用。 或者一个字节码操作库可能需要升级,从而产生连锁反应。 因此,虽然中间地带是一个可能的退路,如果你陷入困境,它远不是一个没有风险的解决方案。

一些额外的链接

Spring框架在一个视频中表达了它对Java 12的政策。 关键部分是。

Jaba 8和11是我们正式支持的LTS分支,对两者之间的版本提供最大的支持...如果你打算升级到12...我们非常愿意与你合作...但它们不是正式的生产支持。长期支持版本是我们主要关注的内容。Java 12和更高版本将是我们方面的最大努力。

作为一个典型的软件供应商的例子,Liferay表示。

Liferay已经决定我们不会对JDK的每个主要版本进行认证。 我们将选择跟随甲骨文的步伐,只认证那些标记为LTS的版本。
Liferay博客

甲骨文官方关于新发布模式的 "误解 "幻灯片

摘要

我相信一些开发团队会采用Java的发布模式,我希望他们能睁大眼睛。 我知道我们在日常工作中不会很快采用发布模式,一个关键的障碍是我们对AWS Lambda的使用,但我也会关注所有其他问题。

欢迎留言,特别是如果你认为我错过了任何应该在考虑清单上的要点。