Jlink无法找到module-info.class及Maven项目模块识别异常
解决Jlink模块冲突与找不到模块的问题
问题分析
你碰到的这两个错误其实是连锁反应,核心原因可以拆解为两点:
- 第一个错误(Two versions of module foo found):Maven编译后会把类文件输出到
target/classes目录(这个目录本身就是一个有效的模块,因为包含module-info.class),同时maven-jar-plugin会把这些类打包成target/foo.jar(同样包含module-info.class)。当你把整个target目录加入模块路径时,jlink会扫描到这两个都属于foo模块的资源,自然会提示冲突。 - 第二个错误(Module foo not found):这说明你打包的
foo.jar没有被jlink识别为有效的模块,大概率是module-info.class没有被正确放在jar的根目录下,或者打包时被遗漏了。
解决方案
步骤1:确保模块描述符位置正确
保证你的module-info.java文件放在src/main/java的根目录下(不是任何子包),这样编译后它会出现在target/classes的根目录,打包进jar后也会位于jar的根目录——这是jlink识别模块的必要条件。
步骤2:检查Maven编译插件配置
maven-compiler-plugin 3.7.0支持模块化编译,你需要确保配置正确处理模块。在pom.xml中添加或更新插件配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <!-- 指定你使用的JDK版本,必须是支持模块化的版本(比如11+) --> <release>11</release> <!-- 确保编译时模块路径正确 --> <modulepath>${project.build.directory}/classes</modulepath> </configuration> </plugin>
步骤3:确保Jar插件正确打包模块描述符
默认情况下maven-jar-plugin会包含module-info.class,但如果你的pom有过滤规则可能会遗漏。显式配置Jar插件确保它被包含:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.2.0</version> <!-- 选择兼容compiler 3.7.0的版本 --> <configuration> <includes> <include>module-info.class</include> <include>**/*.class</include> </includes> </configuration> </plugin>
步骤4:验证Jar包的有效性
执行以下命令检查jar包是否包含正确位置的模块描述符:
jar tf target/foo.jar
输出结果里应该能看到module-info.class在根目录(没有任何前缀路径)。
步骤5:正确执行Jlink命令
- 如果想直接用编译后的类目录(适合开发阶段):
jlink --module-path $JAVA_HOME/jmods:target/classes --add-modules foo --output jre - 如果想用打包后的jar包(适合生产环境):
jlink --module-path $JAVA_HOME/jmods:target/foo.jar --add-modules foo --output jre
注意:不要同时把target目录和target/foo.jar加入模块路径,避免重复模块冲突。
内容的提问来源于stack exchange,提问作者MaxPower
相关产品推荐
相关产品推荐

