“检测到所需的基于文件名的自动模块”是啥意思。警告是啥意思?

Posted

技术标签:

【中文标题】“检测到所需的基于文件名的自动模块”是啥意思。警告是啥意思?【英文标题】:What does "Required filename-based automodules detected." warning mean?“检测到所需的基于文件名的自动模块”是什么意思。警告是什么意思? 【发布时间】:2018-03-12 01:55:48 【问题描述】:

在我的多模块项目中,我只为几个模块创建了module-info.java。在使用maven-compiler-plugin:3.7.0 编译期间,我收到下一个警告:

[警告] * 检测到所需的基于文件名的自动模块。请不要 将此项目发布到公共工件存储库! *

这是什么意思?那是因为我只有几个带有module-info.java 的模块而不是整个项目吗?

【问题讨论】:

我喜欢这个问题,因为人们关心他们代码中的警告,即使我第一次看到它也很困惑。 :) 【参考方案1】:

自动模块回顾

显式模块(即带有module-info.java 的模块)只能访问它需要的模块代码(暂时忽略implied readability)。如果所有依赖项都是模块化的,那就太好了,但如果不是呢?如何引用非模块化的 JAR?

Automatic modules 是答案:任何以模块路径结尾的 JAR 都会变成一个模块。如果 JAR 不包含模块声明,则模块系统会创建一个具有以下属性的自动模块:

推断名称(这是这里的重要部分) 读取所有其他模块 导出所有包

Maven 依赖于该机制,一旦您创建了 module-info.jar,它会将所有依赖项放在模块路径上。

自动命名

有两种方法可以推断自动模块的名称:

清单中的条目 从JAR文件名猜测

在第一种情况下,名称是由维护者故意选择的,因此可以假定它是稳定的(例如,当项目模块化时它不会改变)。第二个显然在整个生态系统中不稳定 - 并非所有项目设置都会导致其依赖项的文件名完全相同。

什么意思?

警告的原因是您的一些依赖项是自动模块并且没有在清单中定义它们未来的模块名称。相反,它们的名称是从文件名派生的,这使得它们不稳定。

稳定名称

那么为什么不稳定的名称会成为这样的问题呢?假设您的库使用requires guava 发布,而我的框架使用requires com.google.guava 发布。现在有人在我的框架中使用你的库,突然他们需要模块路径上的模块 guavacom.google.guava。这个问题没有无痛的解决方案,所以需要预防!

怎么样?例如,阻止开发人员发布依赖于基于文件名的自动模块的工件。 ?

【讨论】:

“这个问题没有无痛的解决方案”......好吧,实际上确实存在无痛的解决方案。不要按身份要求模块,而是按能力要求模块,例如他们导出的包。但当然,该解决方案被拒绝,不可避免地导致您描述的确切问题。要是有人警告过他们就好了…… 需要包而不是模块会使描述符像类开头的导入一样嘈杂和无用。很有可能,它们甚至会自动生成,在不提供任何价值的基础上增加一个额外的构建步骤。我很高兴依赖于模块,而不是包。 OSGi 已经这样做了 18 年,是的,我们在运行时工件中生成它们。在构建时,我们当然会使用工件依赖项。有趣的是,您说这在解决您描述自己的确切问题时没有任何价值。 @NeilBartlett 和 OSGi 的采用,进展如何? 应用服务器没有实现 OSGi 规范吗?【参考方案2】:

[警告] * 检测到必需的基于文件名的自动模块。请不要 将此项目发布到公共工件存储库! *

是因为我只有几个带有 module-info.java 的模块,而不是整个项目吗?

不,这不是因为module-info.java 上列出的少数模块,而是由maven-compiler-plugin 为模块图中的所有automatic modules 生成的。


这是什么意思?

可能坚持不发布当前项目,因为自动模块预计将由其所有者转换为命名或显式模块,然后发布到存储库,这也可能导致其模块名称发生更改。另外这里要注意的一点是,根据 Maven 的进度文档 ~> Java+9+-+Jigsaw,它们还没有完全准备好与 JDK9 兼容的插件版本。


只是为了描绘这样一个用例的例子。考虑这些行 -

我已经发布了一个工件com-foo-bar:1.0.0-SNAPSHOT:jar。 我的另一个项目com-xyz:1.0.0 依赖它。 最终你的一个项目依赖于com-foo-bar,通过com-xyz传递

你计划模块化你的代码并使用类似的东西

module your.module 
    requires com.foo.bar;
    requires com.xyz;

(需要在模块声明中单独specify the transitive dependencies)

一切正常,但直到我决定模块化我的库。 现在,我做的第一件事就是为我的模块命名

我做了一些很棒的事情来明确地表达我的努力:-

module modular.com.foo.bar 

我最终会破坏任何依赖库的代码,并最终以模块化方式破坏任何依赖于您的库的代码。

注意:我同意不练习在生产中使用 SNAPSHOT,但在某些情况下,最终您可能会依赖仍处于开发阶段的工件。


编辑:来自@khmarbaise 的 cmets

它理解人们希望发布到工件,但是 如果他们不知道后果,您将被殴打 未来由此而来。

Maven 想明确指出,这种情况下的 WARNING 非常 严重的,这可能是一个失败,但那本来是一个 糟糕的用户体验需要处理。

解决这个问题的理想方法是库所有者计划将他们的工件迁移到 JDK9,并且自下而上遍历树,在这种情况下,命名/显式模块将是唯一流行的方面,而不需要自动模块名称和此类警告。

【讨论】:

也许我误解了一件事,但消息意味着构建中的模块没有明确定义它自己的名称,这意味着该名称将基于自动模块假定,这意味着永远不会发布这是公开的,也不是像这样使用它,因为您正确地描述了基于自动模块名称的名称可能会改变,这将导致非常糟糕的事情......这与 Maven 插件无关? @khmarbaise 这与 Maven 插件无关?.. 如果这就是我的问题。它确实与检查模块名称是否与模块的源文件名相同的编译器插件有关(检查其是否基于自动模块名称),对吗?或者我可能没有完全理解你的意思。 我理解发布到人工制品的愿望,但如果你不知道后果,你将来会被这个打败。 不,对不起,不要弄错了......我想明确指出,这种情况下的警告非常严重......也许这应该是失败,但这对于大多数 Maven 用户..;-(...除此之外 wiki 页面上的列表可能不是最新的...我需要重新检查该站点... @nullpointer 有没有办法让 maven 告诉我,哪个依赖项实际上会导致警告?我用--debug 运行了 maven,但没有给我关于警告的更多信息,警告完全消失了。【参考方案3】:

maven-compiler-plugin v3.7.0 是一条信息性消息。不知道为什么您将其视为警告...

这是我使用module-info.java 构建基于 Java 10 的项目时得到的结果:

[INFO] Required filename-based automodules detected. Please don't publish this project to a public artifact repository!

【讨论】:

我将其视为警告(maven-compiler-plugin 版本 3.8.1 使用 Java 11)。

以上是关于“检测到所需的基于文件名的自动模块”是啥意思。警告是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

这个安全警告是啥意思(.Net Process 类)?

C4250 VC++ 警告是啥意思?

Chrome Profiler 中的“未优化”警告是啥意思?

animator.startAnimation -- 这个警告是啥意思?

“警告无法确定响应正文的内容长度”是啥意思。意思是我如何摆脱它?

进度警告:在过程中超出 -s 堆栈。那是啥意思?