JPMS/Jigsaw模块中缺少主类

11

我正在尝试创建一个可执行的模块化 jar 文件,可以在 Java 9.0.1 上使用 java -p <jar file> -m <module> 命令运行。

当使用jar cfe test.jar test.Main -C classes/ .命令创建jar文件时,这个目标可以达成,但是使用mvn packagemvn assembly:single命令生成的jar文件会抛出错误:module test does not have a MainClass attribute, use -m <module>/<main-class>

即使是由 maven 生成的这些 jar 文件,在 classpath 中也能够用 java -jar test.jar 命令正常工作,同时也可以通过 java -p test.jar -m test/test.Main 命令实现相同的效果。


我使用jar xf test.jar命令检查了 jar 文件的内容,并发现除了清单(manifest)之外,这些 jar 文件完全相同(见下文):

Manifest-Version: 1.0
Created-By: 9.0.1 (Oracle Corporation)
Main-Class: test.Main

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: testuser
Build-Jdk: 9.0.1
Main-Class: test.Main

值得注意的是,在指定工作清单时仍无法使用java -p test.jar -m test

$ jar cfm test.jar test-contents/META-INF/MANIFEST.MF -C classes/ .
$ java -p test.jar -m test

module test does not have a MainClass attribute, use -m <module>/<main-class>

编辑: 一个具有预期行为的repo:https://github.com/deontologic/test


我正在使用最新的(3.1.0)程序集插件,但我认为它不是Maven特定的。只有在通过“jar”指定主类时,我才能创建可执行的jar文件。 - kantianethics
@nullpointer 我添加了一个仓库,希望自述文件能够澄清预期的行为。 - kantianethics
是的,确切地说。奇怪的是,当使用jar --main-class时它可以正常工作。 - kantianethics
2
是的,它们是不同的!Maven缺少ModuleMainClass指定符。这里有一个未解决的问题:https://issues.apache.org/jira/browse/MJAR-238。感谢您的帮助! - kantianethics
1
需要理解的主要内容是JAR清单中的Main-Class属性适用于可执行JAR(java -jar),它与module-info.class文件中的ModuleMainClass类文件属性不同。当您使用--main-class或-e选项时,jar工具会同时设置两者。当清单文件包含Main-Class属性时,jar --manifest-file或-m选项不会添加或更新ModuleMainClass类文件属性。 - Alan Bateman
显示剩余3条评论
1个回答

6

我在 jar 工具 的文档中没有找到准确的说明,但是jmod工具对其进行了更好的定义。

--main-class class-name 

Specifies main class to record in the module-info.class file.

我可以进一步查看JDK代码,执行不同命令时的行为似乎与ModuleDescriptor.mainClass()mainClass属性有关。因此,在使用--main-class标志打包jar文件时,模块描述符中的条目应该被制作成在执行期间无需指定主类的完全限定名称即可执行模块。另一方面,这在使用Maven jar创建时并非如此,并且可能会在将来的升级中得到修复,就像你发现的那样。
更多关于以下内容为什么有效的信息:
java -jar test-1.0.0-SNAPSHOT-jar-with-dependencies.jar

如果指定了-jar选项,则其参数是包含应用程序的类和资源文件的JAR文件的名称。启动类必须在其清单文件(META-INF/MANIFEST.MF)中的Main-Class清单头中指示。
显然,指定完全限定名称的原因如下:
java -p target/test-1.0.0-SNAPSHOT-jar-with-dependencies.jar -m test/test.Main

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接