迁移到Java 9 + / Java 11时是否需要切换到模块?


80

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

是否需要实际切换到模块?这会产生不必要的费用恕我直言。任何建议或进一步的阅读材料表示赞赏。

为了明确起见,如果不使用模块就使用Java 9+代码是否会有后果?它可以例如与其他代码不兼容吗?


10
这与您在Java 8中已经面临的风险相同:最终出现在“ Classpath Hell”中。

4
sotms /#总结会回答在一定程度上。您可以检查项目目标是否与项目Jigsaw对齐。除此之外,我认为这是与时俱进的问题,对于为消费者提供支持的图书馆/服务也很重要。
纳曼

4
@Taschi我认为,单独的类路径地狱并不能证明模块化是合理的,因为Java 9之前的所有代码都存在该问题,并且在大多数情况下,我们对此没问题(个人从来没有遇到过问题)。
Younes EO

1
@Naman提出项目拼图的目标确实是一个很好的论据。
Younes EO

8
@Younes El Ouarti,消除“ Classpath Hell”是Jigsaw项目的两个既定目标之一。如果您认为这不是与拼图游戏打交道的充分理由,那么……我同意您的看法,并且我会尽可能地避免使用拼图游戏。

Answers:


132

没有。

无需切换到模块。

从未需要切换到模块。

Java 9和更高版本通过未命名模块的概念在传统类路径上支持传统JAR文件,并且很可能会在宇宙热死之前这样做。

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

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

如果您从事的大型项目多年来难以维护,那么模块化带来的清晰性和纪律性可能会有所裨益,但这也可能需要大量工作,因此在开始之前请仔细考虑。

如果您要开始一个新项目,那么我强烈建议您从模块开始。到目前为止,许多流行的库已经升级为模块,因此很有可能您所需的所有依赖项都已经以模块化形式提供。

如果您维护一个库,则强烈建议您将其升级为模块(如果尚未升级),并且所有库的依赖项都已转换。

这并不是说您在经过Java 8时不会遇到一些绊脚石。但是,您遇到的那些障碍可能与模块本身无关。我们听说过,因为我们的Java 9在2017年发布的最常见的迁移问题有做更改版本字符串的语法和对去除或内部API的封装例如sun.misc.Base64Decoder),针对公众,支持更换有已经可用多年了。


26

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

另一方面,客户端库则完全不同。我不能告诉你有时候我们一团糟。我将解释我以前讨厌的一点jigsaw。您向客户端公开一个界面,供所有人使用。自动认为interfacepublic-暴露给世界。通常,我所要做的就是拥有一些package-private不使用该接口的类,这些类不会暴露给客户端。我不希望客户使用它,这是内部的。听起来不错?错误。

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

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

当它增长时(在我们的情况下确实如此),这些软件包太大了。您说要转移到单独的包裹吗?当然,而是那时,HelperUsage并且FactoryUsage将是public我们尽量避免从一开始。

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

modules解决这个问题的一个美丽的方式:public是不是真的 public了; 我可以friend通过exports to指令访问。这使我们的代码生命周期和管理变得更加容易。而且我们摆脱了classpath的地狱。当然maven/gradle,主要是为我们解决这个问题,但是当出现问题时,痛苦将是非常真实的。也可能有许多其他示例。

话虽如此,过渡仍然不容易。首先,团队中的每个人都需要保持一致。第二是障碍。我仍然看到的最大的两个是:如何根据具体内容分开每个模块?我还没有确切的答案。第二个是split-packages,哦,美丽的“相同的类由不同的模块导出”。如果您的库发生这种情况,有多种方法可以缓解;但是如果这些是外部库,那就那么容易了。

如果您依赖jarAjarB(单独的模块),但是它们都导出abc.def.Util,那么您会感到惊讶。不过,有多种方法可以解决此问题。有点痛苦,但可以解决。

总体而言,由于我们迁移到了模块(并且仍然这样做),所以我们的代码变得更加简洁。如果您的公司是“代码优先”的公司,那么这很重要。另一方面,我曾参与过一些公司,被高级建筑师视为“太贵”,“没有真正的利益”。


4
感谢您的煽动!所以我得到的是,模块化带来了我们以前版本中所缺少的急需访问限制。我绝对可以看到这对库有什么用。如果通过REST / AMQP / etc与服务进行通信。这又不是什么大问题,或者说,没有好处吗?也许我们不能随意地说所有Java 9+代码都应该是模块化的?因此,我们应该将其视为“工具”本身吗?但是很有趣。
Younes EO

您可能会发现有用的是“访问器” API模式(但请注意,最好使用带有方法的私有字段,而不是公共静态字段,以避免在类加载期间出现死锁)。在这里看到:wiki.netbeans.org/...
托马什Myšík

感谢您分享经验!如果您可以共享更多细节或您提到的令人痛苦但仍可以解决的问题的链接,那将是很好的。
botismarius

3
“第二个问题:我们客户的任何用户/调用者都可以创建相同的程序包名称并扩展这些隐藏的类。” 早在Java 9之前,就可以密封软件包以防止这种情况发生。(我碰巧认为模块是一个好主意,我在所有项目中都使用了它们。我只是想指出,这种特殊的用例不需要它们。)
VGR
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.