迁移到 Java 9 或更高版本时是不是需要切换到模块?

Posted

技术标签:

【中文标题】迁移到 Java 9 或更高版本时是不是需要切换到模块?【英文标题】:Is there any need to switch to modules when migrating to Java 9 or later?迁移到 Java 9 或更高版本时是否需要切换到模块? 【发布时间】:2020-11-07 01:33:30 【问题描述】:

我们目前正在从 Java 8 迁移到 Java 11。但是,升级我们的服务并没有我们预期的那么痛苦。我们基本上只需要更改build.gradle 文件中的版本号,服务就可以愉快地启动并运行。我们升级了库以及使用这些库的(微)服务。到目前为止没有问题。

是否有任何需要真正切换到模块?恕我直言,这将产生不必要的成本。任何建议或进一步阅读材料表示赞赏。

澄清一下,如果在不引入模块的情况下使用 Java 9+ 代码会有什么后果吗?可以吗?变得与其他代码不兼容?

【问题讨论】:

这与您在 Java 8 中已经面临的风险相同:最终陷入“类路径地狱”。 sotms/#summary 会在一定程度上回答。您可以检查您的项目目标是否与项目Jigsaw 一致。除此之外,在我看来,更新对于图书馆/服务向消费者提供支持也很重要。 @Taschi 我不认为类路径地狱本身就证明了模块化是合理的,因为 Java 9 之前的所有代码都有这个问题,而且在大多数情况下我们都很好(个人从来没有遇到过这个问题)它)。 @Naman 提出拼图项目的目标确实是一个很好的论据。 @Younes El Ouarti,移除“Classpath Hell”是 Project Jigsaw 的两个既定目标之一。如果您认为这不是与 Jigsaw 打交道的充分理由,那么……我同意您的观点,并且我会尽可能避免 Jigsaw。 【参考方案1】:

没有。

无需切换到模块。

从未需要切换到模块。

Java 9 及更高版本支持传统的 JAR 文件 传统的类路径,通过未命名模块的概念,将 可能会一直这样做,直到宇宙热寂。

是否开始使用模块完全取决于您。

如果您维护一个变化不大的大型遗留项目, 那么它可能不值得努力。

如果您从事一个难以维护的大型项目 模块化带来的清晰度和纪律性 可能是有益的,但也可能是很多工作,所以想想 在开始之前请仔细。

如果您要开始一个新项目,那么我强烈建议您从 如果可以的话,模块。到目前为止,许多流行的图书馆都是upgraded to be modules,所以有一个很好的 您需要的所有依赖项都有可能已经可用 以模块化形式。

如果您维护一个库,那么我强烈建议您 如果您还没有这样做,请将其升级为一个模块,并且如果所有 您的库的依赖项已被转换。

这一切并不是说你不会遇到一些绊脚石 超过 Java 8 时。但是,您确实遇到的那些将, 可能与模块本身无关。最普遍的 自从我们发布 Java 9 以来我们听说过的迁移问题 2017 年与 changes to the syntax of the version string 和 removal or encapsulation of internal APIs 有关 (例如sun.misc.Base64Decoder)公开,支持 多年来一直有替代品。

【讨论】:

【参考方案2】:

我只能告诉你我的组织对此事的看法。对于我们正在进行的每个项目,我们正在迁移到模块。我们正在构建的基本上是微服务 + 一些客户端库。对于微服务,向modules 的转换在某种程度上是一个较低的优先级:那里的代码已经以某种方式隔离在 docker 容器中,因此在其中“添加”模块似乎(对我们而言)不是很重要。这项工作进展缓慢,但优先级较低。

另一方面,客户端库是一个完全不同的故事。我不能告诉你我们有时会遇到什么混乱。我将解释我在jigsaw 之前讨厌的一点。您向客户端公开一个接口,供所有人使用。自动interfacepublic - 暴露给世界。通常,我所做的是有一些 package-private 类,它们不向客户端公开,使用该接口。我不希望客户使用它,它是内部的。听起来不错?错了。

第一个问题是,当package-private 类增长时,您需要更多类,唯一隐藏所有内容的方法是在相同包中创建类:

  package abc:
        -- /* non-public */ Usage.java
        -- /* non-public */ HelperUsage.java
        -- /* non-public */ FactoryUsage.java
        ....

当它增长时(在我们的例子中是这样),这些包太大了。搬到你说的单独的包裹?当然可以,但是 HelperUsageFactoryUsage 将是 public,我们从一开始就试图避免这种情况。

问题二:我们客户的任何用户/调用者都可以创建相同的包名称并扩展那些隐藏的类。我们已经发生过几次了,很有趣。

modules 很好地解决了这个问题:public 不再是真的 public;我可以通过exports to 指令访问friend。这使我们的代码生命周期和管理更加容易。我们摆脱了类路径地狱。当然maven/gradle 主要是为我们处理,但是当 出现问题时,痛苦将是非常真实的。还有很多其他的例子。

也就是说,过渡(仍然)并不容易。首先,团队中的每个人都需要保持一致;二是有障碍。我仍然看到的最大的两个是:你如何分离每个模块,具体基于什么?我还没有确定的答案。第二个是split-packages,哦漂亮的“同一个类被不同的模块导出”。如果您的库发生这种情况,有办法缓解;但如果这些是外部库...不容易。

如果您依赖jarAjarB(单独的模块),但它们都导出abc.def.Util,您会大吃一惊。不过,有一些方法可以解决这个问题。有点痛苦,但可以解决。

总的来说,自从我们迁移到模块(现在仍然如此)后,我们的代码变得更加更简洁了。如果您的公司是“代码优先”的公司,这很重要。另一方面,我参与过一些被高级架构师视为“太贵”、“没有真正好处”的公司。

【讨论】:

感谢您的鼓励!所以我得到的是,模块化伴随着我们在以前的版本中缺少的非常需要的访问限制。我绝对可以看到这对图书馆有什么用处。如果通过 REST/AMQP/等与服务通信。这又不是什么大问题,或者更确切地说,没有好处?或许我们不能随便说all java 9+代码应该是模块化的吧?那么我们应该把它本身看作是一个“工具”吗?不过很有趣。 您会发现有用的是一种“访问器”API 模式(但请注意,最好使用带有方法的私有字段而不是公共静态字段,以避免在类加载期间出现死锁)。见这里:wiki.netbeans.org/… 感谢您分享您的经验!如果您能分享更多细节或链接到您提到的痛苦但仍然可以解决的问题,那就太好了。 “问题二:我们客户的任何用户/调用者都可以创建相同的包名称并扩展那些隐藏的类。”早在 Java 9 之前,包可能是 sealed 以防止这种情况发生。 (我碰巧认为模块是一个好主意,我在所有项目中都使用它们。我只是想指出这个特定的用例不需要它们。)

以上是关于迁移到 Java 9 或更高版本时是不是需要切换到模块?的主要内容,如果未能解决你的问题,请参考以下文章

markdown 在iOS 11或更高版本上将数据从V3迁移到V4

Django - 安装 mysqlclient 错误:需要 mysqlclient 1.3.13 或更高版本;你有 0.9.3

Bootstrap 的 JavaScript 需要 jQuery 版本 1.9.1 或更高版本

如何使使用旧 Java 版本开发的应用程序在 jdk 9 或更高版本上运行? [复制]

如何在 java 10 或更高版本 java 11 中运行现有的 JAVA Web 启动应用程序

检查 iOS 版本是不是与 PHP 兼容,从 iOS 3.0 到 IOS 4.0 或更高版本