跳转到主要内容
Chinese, Simplified

霍夫曼:我叫马克·霍夫曼。从第一个版本1.0开始,我就一直在使用Java。从那时起,我在每个版本中都做Java项目。作为背景,我想告诉你们我今天在做什么。这就是我白天做的事。正如您在这里看到的屏幕截图所示,这些系统管理铁路交通。铁路实际上是一块有150多年历史的土地。这听起来像是遗留系统。事实上,我们开发和维护此类系统已经超过15年。实际上,这些系统有一个真实的商业案例,并提供了真正的价值。他们确实工作。也许,你也处在类似的情况下,你不能只挑选最新最闪亮的软件工具和特性,每隔一天就开发一个新项目。您所使用的系统为您的客户、公司提供了一些价值,并且需要长期维护。事实上我对此很感兴趣。您当前使用的软件有多旧?您目前在生产中使用的Java版本是什么?这是我的一个例子。这个软件大约有15年的历史了。在生产中,我们有Java11。

我在晚上做什么

我做更多的事情。我把它叫做我晚上做的事。我参与了一些开源项目,可能最著名的是JaCoCo代码覆盖工具。使用该工具,您可以测量单元测试提供的覆盖率。我创建这样的报告。它在QA领域非常流行。它可以在最新的Java版本上工作,这看起来真的是一种很好的技术,可以适应JVM中的最新技术和最新特性。

让我们来看看新的和闪亮的开源项目的现实。我从事的项目已经有10多年的历史了。杰科科,我10年前开始的。Eclipse插件的代码覆盖率已经有15年了,它基本上是以前的另一个工具。这些工具已经发布了相当多的Java版本。实际上,这是JaCoCo的大矩阵。目前,我们支持Java5到Java17。所有这些JDK实际上都在我们的构建管道中使用。集成测试在这些管道上运行。这是开发库时出现的情况。

不同种类的软件

基本上有两种不同的软件项目。您可以使用产品或特定于项目的解决方案。在这里,您只需选择最能满足您的需求的运行时。您只能运行特定的运行时版本。如果您对一个工具或库更感自豪,那么您必须支持多个运行时,因为您不知道您的客户机,并且您的客户机可能会将您的应用程序用于不同的运行时。对于上下文,我将重点讨论第一个,假设您在生产中有一个大型应用程序,并且希望定期更新它们。

为什么要升级你的应用

这里的问题是,首先,为什么要更新应用程序?第二,如何?让我们看看为什么。通过新的Java版本,我们获得了新的有用的语言特性和新的API。这使您的工作效率更高,并且您希望使用它来获得更好的代码库、更干净的代码库,并在开发新功能和维护代码库方面更高效。第二,有很多错误修复和安全修复正在进行。您希望有一个维护版的Java,以获得这些错误修复和安全修复。有了新的平台。我这里有一个例子,这是目前非常流行的,ARM架构,新处理器。你可能从和你一起玩的树莓皮上就知道了。这是一个非常好的学习平台。此外,在生产方面,我们将看到更多,最值得注意的是,最新发布的用于新笔记本电脑的苹果M1处理器。我们现在有了基于ARM架构的Windows10。在Amazon上,A1实例类型也基于ARM,并且越来越公开,因为它们提供了非常好的功率和价格比。它们真的很划算。我们可能会看到更多的应用部署在ARM架构上。我们需要新的JVM和新的运行时,它们已经支持这种体系结构。对于Java5,您不会得到这样的结果。

我们可能非常依赖第三方库,我们需要不时地对它们进行升级。这些库还具有Java运行时的最低要求。我们需要不时地更新我们的运行时,然后我们还可以更新库。目前,我对Maven Central做了一些研究,大多数最新版本的库都以Java8为基准。没有恐慌,Java8已经存在了八年多了。至少有一点是很好的,那就是Java8,Java库不会很快地增加到Java11。它们运行运行时,但您不需要立即更新到Java11。请注意,大多数库现在都在Java8上。如果您的版本早于Java8,那么在更新它们时可能会遇到麻烦。当然,我们想成为快乐的开发者,而你想学习和使用最新的东西。在生产环境中的开发环境中拥有不止一个运行时是一个很好的动机。

 

如何升级

让我们看看主要部分,我们如何更新?这里是旧Java时代的发布时间表。我们在这里看到的是每两年发布一次,比如两年。Java6和Java7之间存在巨大的差距。这是甲骨文收购Sun的时候。这已经五年了。五年来,我们没有看到一个新的语言特性或一个新的API,所以您从Java6开始。在这些Release之间,什么都没有,只有沉默。您将无法获得一些预览功能。您将无法获得一些增量更新。只是你等了几年,突然间你得到了一个新版本。OpenJDK改变了这一点。在OpenJDK中,新的时间表是从Java9开始的。现在我们每六个月发布一次新版本。以固定周期每年发布两次。当我们查看发布的生命周期时,我们看到大多数发布只维护了六个月。其间,我们发布了长期支持版本。当前的长期支持版本是Java8、Java11,下面的下一个版本是Java17,将于今年秋天发布。实际上,时间表还是一样的。每隔几年,我们就会有一个主要的版本,有一个长期的发布计划,但在这期间,我们会有新的中间版本,我们已经可以测试和适应新的特性了。

可持续的更新战略

什么是可持续更新战略?首先,真正确保您在生产中有一个受支持的JDK。目前,我们使用的是Java8。Java8可能还要支持几年。如果您运行的是Java5或其他版本,那么没有理由不更新到至少Java8。这是一个非常笼统的建议。您应该有一个干净的代码库,但是对于Java运行时,请注意不推荐使用的API。在最新的Java版本中,弃用注释被一个新属性ForRemove扩展。如果ForRemove设置为true,这意味着有认真的计划来删除它。这已经发生了。如果您选择忽略不推荐的API,总有一天,您的代码库将不再编译,因为API将消失。注意这个。另一件事是内部API。依赖内部API、com.sun或sun包是一种不好的做法,它们现在被Java模块系统封装,访问它们变得更加困难。您将首先收到警告,然后在下一个版本中,您将无法再访问这些内部API。避开它们。实际上没有理由依赖内部API,只使用公共API和Java包。

如果JVM有运行时警告,打印到控制台,打印到日志文件,请认真对待。它们通常会提示您正在使用两个内部API,您正在使用不推荐的JVM参数。修好它们,因为总有一天它会坏的。更新你的工具。这些工具,比如说IDE,构建工具,它们在追赶最新的Java版本方面做得非常好。如果您更新您的IDE,您将很容易引入新的Java版本,因为这些工具很可能支持最新的Java版本。另外,更新您的依赖项。此外,您的第三方依赖项可能会使用内部API或不推荐使用的API,因此它们通常会不时发布更新,并清理其代码库。为避免您的第三方依赖关系出现问题,请随时更新它们。只需确保库不需要比当前更新的JDK版本。大多数Library都非常保守。就像我们在JaCoCo一样,我们仍然在使用Java5。Maven Central上的大多数库都可以使用Java8。

安全的更新战略

当涉及到在生产环境中实际更新运行时时时,比如说在大型系统中,您希望安全。你要确保不破坏生产。你想确保万一出了什么问题,你仍然可以以某种方式逃离这种情况。这是我的建议,我们在大型生产系统中多次采用的方法是分两步进行。第一步是更新运行时JDK。测试一下。把它投入生产。这方面的经验。它有用吗?它是否满足您的非功能性需求?你有什么问题吗?你觉得有什么问题吗?只有在成功的情况下,才能采取第二步,即更新您的开发目标。为新版本编译。使用新功能。为新版本编译字节码。

这看起来像这样。如果这些是您的发行版,您将始终首先更新运行时JDK。然后,对于软件的下一个版本,如果您成功地更新了运行时,您还将更新您的开发构建链。这给了你一个安全网。因为如果在运行时、测试期间,甚至在生产中出现故障,您总是可以返回到旧的运行时并花时间解决问题。如果您同时更改开发版本,或者从一开始就更改开发版本,那么您就打开了使用新API、使用新语言功能的大门。没有回头路了。如果出现问题,您不能直接切换回以前有效的旧版本。这是一种保守的方法,特别是对于大型系统,在这些系统中,您可以确保在生产环境中运行时是安全的。一旦您有了这种信心,您还可以将开发堆栈移动到新版本。我真的很推荐。

潜在的更新问题

更新的潜在问题是什么?JVM会不时发生变化。它有数百个命令行选项,这些选项会改变。他们被弃用了。他们走了。语义有时会有一些变化。Chris Newland的VM Option Explorer是一个很好的工具,所以请查看该站点。您可以探索每个Java版本的选项,并查看两个Java版本之间的差异。这有助于您理解在您的产品配置中可能会发生什么变化,以及您应该考虑哪些JVM选项替代其他东西。在清理JDK并使其现代化的过程中,OpenJDK团队决定删除一些Java企业API,主要是在javax包中。它们只是从JDK中消失了,比如javax.transaction或javax.xml.bind。例如,javax.xml.bind,我们对xml接口使用了很多,其中我们有用javax.xml.bind注释的接口Java类。你需要在Maven Central找到替代品。在Maven Central中,您将找到所有这些包的API和变体,并且您需要正确地声明对这些替换的依赖关系,以确保您的应用程序使用更新的版本运行,其中该包已被替换。这主要发生在Java11上。在Java11中,所有这些包都被删除了

您可能已经使用的内部API将被封装。在像Java16这样的较新版本中,您至少会收到警告。默认情况下,它将不再工作,因此代码将爆炸。一旦你启动应用程序,你会得到一个异常,这个类不再可访问,你就完成了。为此采取措施。有两种选择。一种选择是,使用jdeps工具进行静态分析。jdeps工具可以查看您的类文件、char文件,并查找对内部类和报告的依赖关系,这样我们就可以完整地了解您的代码库,并查看可能隐藏的内容、一些内部访问。另一件事是,在运行时执行。有一个--非法访问开关,它有两个选项,其中一个选项是调试选项。调试选项将打印详细报告。在运行时,如果您的代码库遇到内部API,那么您可以尝试修复该问题。

对于非长期支持版本怎么办?

我之前已经告诉过您非LTS版本,所以在主要的长期支持版本之间只有六个月的可用版本。你应该怎么处理它们?我个人的建议是用它们实际测试您的软件,并尽早发现潜在的问题。您将准备好看到,我的软件将遇到什么问题,可能什么API将消失。重构需要什么?我现在在哪里使用不推荐的API?也许运行时本身也会遇到一些问题,比如崩溃,或者出现一些意外行为。这是一个向OpenJDK项目报告这一点的好机会,以便他们能够修复它。实际上,我不建议在生产中使用非LTS版本。因为这意味着您确实需要能够在六个月内将运行时升级到下一个LTS版本或下一个开发版本。除非你不能保证,否则我不会去非LTS版本,因为六个月后,你肯定是在一个未维护的版本上。这是测试它们为下一个LTS版本做准备的好机会。

 

预览的特性

还有一件事,您可能听说过预览功能。编译器和JVM的运行时都有一个新标志--enable preview。这将使您能够访问新的语言功能。您可以在新的JVM特性和新的API上尝试新语言特性的实验实现。只能使用--enable preview标志的API,否则会收到警告。研究新特性、跟踪OpenJDK项目中的实现以及报告反馈,这真的很好。同样,我并不建议您使用--enable preview来运行生产。这些功能尚未最终确定。他们会的,在过去,他们确实改变了。预览的想法是真正从社区获得反馈,实际处理反馈,并根据反馈修改实现或规范。如果您依赖预览功能,您将不得不很快调整代码库,因为它肯定会改变。

问答

Ruiz:当您依赖与最新JDK不兼容的第三方组件时,您对如何跟上最新JDK有何见解?你对此有什么建议或想法?

霍夫曼:首先,我的建议是早点考试。真正拿起开发版本并做好准备。通常,这些库也是以某种方式维护的,也许它们是开源的。如果您及早发现并确定问题,您就有机会提供适当的错误报告,甚至可能会提供一个宣传,或者如果这是一个商业问题,那么尽早通知供应商。然后您就有了一些时间框架和空间来修复和更新库。例如,直到您选择下一个长期发布版本。基本上,可能有一些变通办法。例如,如果库使用内部API,则可以在命令行上打开它。总的来说,我的建议是尽早测试并设法解决根本原因。我们每次都这样做。令人惊讶的是,有多少人实际使用开放源码库,并抱怨它们不能在特定的环境中工作。特别是,在商业环境中,人们实际贡献的回报似乎有一个巨大的障碍,说:“这是一个真正的问题。这是一个快速用户,你能看一下吗?”这很简单。我经常教人们,特别是在商业环境中,对开源环境尽可能少的贡献,只报告问题。这是你迈出的第一步。

鲁伊斯:是的,第一步,报告。你甚至不需要修复它,只需提供反馈。

霍夫曼:提供反馈。如果你是一个快速用户,这是你能做的最好的事情。你根本不必埋头于代码。

Ruiz:提交一个测试用例,比如一个小的可复制的例子。

为什么坚持使用Java?我想知道你的看法,为什么是Java?我们是爪哇人。

霍夫曼:说到科技,我总是尽量避开粉丝。这真的很危险。我总是试图挑战自己并理解,为什么它是一个好的选择,为什么不切换到另一种JVM语言,或者可能转到另一种运行时。首先,Java对我来说已经非常成熟了。它拥有一个真正稳定的运行时环境,这给了您很多好处。我们目前有一个非常积极的发展,并正在向现代语言发展。最后,是关于技术诀窍。你的团队有哪些技能?您的团队在未来10年内可能具备哪些技能?在这里,我认为Java是一个不错的选择。也许你在一家.NET公司工作,也许.NET是更好的选择。比如说,像随机技术一样,你经常会用到,比如,Scala几年来非常流行。现在我们有了一些遗留的Scala代码,没有人想再维护它了。对我来说,如果涉及到一个商业项目,而不仅仅是玩具项目,我真的会考虑哪些诀窍是可行的。

鲁伊斯我们必须在成熟度、功能和支持之间找到平衡。没有多少语言能满足这些要求。人们抱怨Java的一个问题是,有时我们的行动不够快,或者我们没有足够快地摆脱过去。

霍夫曼:老实说,我认为Java实际上发展得太快了。

鲁伊斯:我们不需要迁移或更新。Java 8将在2030年之前得到支持。

您是否计划从Java1.5升级JaCoCo源代码?这样做的好理由是什么?

霍夫曼:目前,我们没有令人信服的理由这样做。JaCoCo是一种工具,用于各种平台上的许多项目。当然,拥有Java8并在所有API中拥有更多的语言特性会更有趣,但这对于像我们这样的库的维护人员来说才是有趣的。对于目前可能在Java6环境中使用它的用户来说,这并不有趣。就功能而言,我们还没有看到任何令人信服的理由这样做。JaCoCo在Java17上工作,只是JaCoCo的实现仍然与Java1.5兼容。它可以完美地使用Java17处理类文件。

鲁伊斯:它仍然做得很好。

您期待在下一个Java版本中有哪些即将推出的功能?

霍夫曼:记录是一种东西,它是语言的补充,就像switch语句一样。这是我非常期待的事情,尤其是记录。这就是问题所在,因为如果你曾经编写过企业软件,getter和setter真的很可怕。我真的希望我们能尽快解决这个问题。

鲁伊斯:对于桌面图形用户界面,你还有其他建议吗?他们从JavaFX开始。

霍夫曼:事实上,我在领导一个为一家大型公司工作的团队,该公司正在研究UI策略。我们决定改用web界面,Java将不再是该特定企业未来用户界面的首选工具。在这个方向上有很强的趋势。在这方面有很多专门技术和工具。我个人的观点,特别是对于商业软件,是我们在未来不会再看到很多JavaGUI了。我认为网络将扮演这一角色。

鲁伊斯:我发现一件事是很难说服人们升级Java版本,这从来都不值得。有什么建议,去和管理员说,我们应该升级?为什么?

霍夫曼:这是一个商业决定。我问了一个问题,你想让这个软件运行多久?您希望让开发人员维护软件多长时间?如果你认真地问这个问题,如果你看看旧Java版本的许可证模型,那么如果你低于Java8,你有两个选择。您需要为许可证、更新或至少更新到Java11支付大量费用,以获得可在生产中使用的免费替代方案。归根结底,这取决于资金和执行能力。您所依赖的大多数库,新版本将不再支持旧的JDK,因为它们升级到Java8甚至Java11。基本上,这是一个生命周期问题。如果你为你的产品烦恼,如果你想在未来几年内维护它,请升级。如果你不在乎,不要要求我添加任何功能。

鲁伊斯:事实上,这更多的是关于,Library是什么?谁来维护它,维护多长时间?漏洞是什么?是否有什么东西可以让我们的软件更快,性能更好?它必须是一天结束时令人信服的理由,而不是因为它是新的。外面有些东西是新的,但这还不够好。

您是否期待下一个LTS中的任何特定功能?不?

霍夫曼:基本上是记录。

鲁伊斯:不是在LTS里。事实上,在cadence中,我们有很多从11到17的功能,所以很难确定一个。因为当他们问我一个特定的问题时,什么版本?我总是说,如果你想一想积累起来的东西,那真的很有趣。如果你想一想,就很难确定。

霍夫曼:当然。我在Java网站上工作,我试着跟踪并把它们都写下来。这也有助于我跟踪并了解最新的功能。其中一些很好,但是我不认为它们很重要,就像我不能在没有新功能的情况下编写软件。我不会那么做的。我不是技术迷。我真的想问,这有什么好处?

鲁伊斯:事实上,这是因为你在这个非常重要的系统中工作,说起来不那么容易,让我们再来一次。它很大。你在处理非常重要的事情。我认为你的失败率应该非常低。

霍夫曼:当然。另外,我们在铁路公司工作。他们习惯了一个完全不同的生命周期。这种列车的生命周期为20或30年。如果你作为一名软件开发人员告诉《铁路人》:“我们去年刚刚开发了这个软件,但今年我们不得不重新编写它,因为有了新技术,等等。”没有人会买这个。

Ruiz:有没有插件工具可以用来分析从一个JDK版本升级到更高版本需要更改哪些内容?

霍夫曼:这是JDK附带的。有两种选择。一种选择是进行静态分析。您可以查看类文件和编译的类文件,并查找内部API使用情况。这是通过JDepend工具实现的。它是JDK的一部分。你不需要插件。您只需在类文件的命令行中运行它,就可以得到结果。另一个是动态部分。默认情况下,现代JDK将在控制台上打印警告。真的看看这个。如果有警告的话,寻找它为什么是警告的根本原因,因为有人认为这会有助于向你展示警告,不要忽视它们。你可以免费得到。你不需要工具。

鲁伊斯:实际上有一个问题,我应该注意措辞吗?是的,至少要看看他们在告诉你什么。如果你现在没有时间修复它,但至少要有意识。这将是我的零级建议。

霍夫曼:如果你决定无视警告,迟早它会咬你的。

Ruiz:在现实世界中,您是否遇到过Java升级或依赖库的系统的生产问题。生产问题,环境可能是活的,也可能是死的,这会让你们感到担忧吗?您对Java升级有任何问题吗?

霍夫曼:当然,我们在Java升级方面有问题,但在生产方面没有。这很重要。我们需要保障措施。这是一种保守的做法。我们首先在生产环境中升级运行时版本。如果我们根据旧的JDK进行构建,我们总是可以后退。如果你有一个生产系统,并且你升级到一个新版本,并且可能你已经测试了一段时间。即使您在生产中遇到问题,您仍然可以返回到旧的运行时,因为您的代码仍然是根据旧的运行时编译的。这就是为什么如果你有一个关键的系统,我真的建议你做这两个步骤,比如,让它在生产几个月。一旦您非常确定这是可行的,您还可以为您的开发人员提供新的JDK版本,并允许他们使用新特性和新API。那就没有回头路了。一旦您打开使用新API的大门,并使用新的语言特性,您就无法对整个热代码进行反向移植。

鲁伊斯:我完全同意你的看法。那张幻灯片是纯金的,因为它指出了重要的事情,比如一旦你打开瓶子,让精灵出来,就没有办法把它放进去。您需要足够的时间在所有可能的情况下测试您需要测试的任何内容。是的,非常重要。

您如何看待使用基于JVM的语言而不是使用Java?例如,科特林。Java需要对这种语言进行很多改进。

霍夫曼:当然。首先,如果您使用不同的JVM语言,您将获得JVM的所有好处。JVM是一个很好的运行时。对我来说,没有理由不使用另一种语言。然后是技术诀窍,以及团队的结构。如果你有一个好的Kotlin基地,同时也有很多好的工具,Kotlin在安全方面也会给你带来很多好处。选择这样一种不同的语言是个不错的选择。请再次扪心自问,你有能力做到这一点吗?你有诀窍吗?你有没有开发人员,或者只是你的个人玩具项目来学习一门新语言?

原文:https://www.infoq.com/presentations/java-update-versions/

本文:http://jiagoushi.pro/node/1532

Tags
 
Article
知识星球
 
微信公众号
 
视频号