Java 9模块配置多共享Java 8依赖:解决重复导出错误
你碰到的是Java模块系统的**拆分包(Split Package)**问题——nd4j.common和nd4j.api两个模块都导出了org.nd4j.linalg.util包,而Java模块系统要求同一个包只能被单一模块导出,这就导致了冲突错误。
不用手动梳理12层子依赖,有几种更高效的解决思路:
一、用Maven快速定位重复包
别再用Excel手动整理了,直接用Maven命令一键找出包含目标包的依赖:
- 查看nd4j相关依赖树:
mvn dependency:tree -Dincludes=*:nd4j-* -Dverbose
- 直接生成所有nd4j依赖的列表,方便查找:
mvn dependency:list -DoutputFile=deps.txt -DincludeGroupIds=org.nd4j
打开生成的deps.txt,就能快速定位哪些jar包包含org.nd4j.linalg.util,不用逐层翻找子依赖。
二、针对性排除重复依赖
找到重复来源后,在pom.xml中给上层依赖添加排除规则。比如如果nd4j-api是某个核心依赖的子依赖,且nd4j.common已经包含了完整的org.nd4j.linalg.util包,就把nd4j-api从该依赖中排除:
<dependency> <groupId>org.deeplearning4j</groupId> <artifactId>deeplearning4j-core</artifactId> <version>你的项目版本</version> <exclusions> <exclusion> <groupId>org.nd4j</groupId> <artifactId>nd4j-api</artifactId> </exclusion> </exclusions> </dependency>
注意:排除前要确认两个模块的包内容是否一致,如果nd4j-api里的该包有独有的类,不能直接排除,这时候用下面的补丁方案。
三、用模块补丁机制合并拆分包
如果两个模块的同包内容互补,无法直接排除,就用Java 9的--patch-module参数把重复包合并到一个模块中。比如把nd4j-api里的org.nd4j.linalg.util补丁到nd4j.common模块:
在Maven的编译插件中添加参数:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <release>9</release> <compilerArgs> <arg>--patch-module</arg> <arg>nd4j.common=${settings.localRepository}/org/nd4j/nd4j-api/你的版本/nd4j-api-你的版本.jar</arg> </compilerArgs> </configuration> </plugin>
运行时也可以用相同的参数,把两个jar的同包内容合并成一个模块的一部分,绕过拆分包的限制。
四、应急方案:临时关闭模块系统
如果赶时间处理其他任务,也可以暂时把项目退回到Java 8模式运行:
- 删除项目中的
module-info.java文件 - 在
pom.xml中修改编译版本:
<properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties>
这只是权宜之计,长期来看还是建议适配模块系统,避免后续版本兼容问题。
内容的提问来源于stack exchange,提问作者Borel

