如何正确抑制“自动模块需要transitive指令”警告?
requires transitive警告 我来帮你理清这个问题——当你在模块描述符里给自动模块加上requires transitive时,javac就会抛出这个警告,原因很简单:自动模块本身没有明确声明它的依赖关系,你把它标记为传递依赖的话,相当于把一个"黑盒"的依赖暴露给了依赖你的模块,这不符合JPMS(Java平台模块系统)的设计初衷。
先简单说下什么是自动模块:自动模块是那些没有module-info.java的JAR包,JPMS会自动把它们识别为模块,名字通常是从JAR文件名推导而来(比如Guava的JAR名一般是guava-xxx.jar,所以模块名是com.google.common)。但这类模块没有明确的导出包、依赖声明,它们的依赖关系是模糊的。
看你给出的示例代码:
module com.example.mymodule { exports com.example.mymodule.myexportedpackage; requires transitive com.google.common; }
这里的requires transitive com.google.common就是触发警告的核心原因——com.google.common是一个自动模块。
下面给你几个可行的解决方案,按推荐程度排序:
方案一:改用普通
requires替代requires transitive
如果你的模块只是自身需要用到Guava,不需要把Guava的API暴露给依赖你的模块,那直接修改模块描述符即可:module com.example.mymodule { exports com.example.mymodule.myexportedpackage; requires com.google.common; }这样既满足了你的模块对Guava的依赖需求,又不会把自动模块的模糊依赖传递出去,警告自然就消失了。
方案二:升级依赖到支持JPMS的显式模块版本
很多流行库(比如Guava)现在已经正式支持JPMS了,你可以升级到带有module-info.java的版本。比如Guava从26.0-jre版本开始就提供了完整的模块支持,模块名还是com.google.common,但此时它是一个显式模块,有明确的依赖和导出声明,这时你使用requires transitive就不会再触发警告了。方案三:抑制警告(不推荐)
如果你确实需要把自动模块的API暴露给下游模块,又暂时没法升级依赖,那可以通过编译参数来抑制这个警告。在Maven的maven-compiler-plugin中添加如下配置:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <release>9</release> <compilerArgs> <arg>-Xlint:-requires-transitive-automatic</arg> </compilerArgs> </configuration> </plugin>不过这个方案只是"掩盖"了警告,并没有解决自动模块依赖模糊的根本问题,所以除非万不得已,不建议采用。
总的来说,这个警告是JPMS在帮你规避依赖传递的风险,优先考虑前两种方案,才是符合模块系统设计理念的正确做法。
内容的提问来源于stack exchange,提问作者Alex Shesterov

