I'm trying to create a modular, executable jar file, that can be run with java -p <jar file> -m <module>
on Java 9.0.1.
This works as expected when creating a jar with jar cfe test.jar test.Main -C classes/ .
, but throws module test does not have a MainClass attribute, use -m <module>/<main-class>
when generated with mvn package
and mvn assembly:single
.
These maven generated jars still work with java -p test.jar -m test/test.Main
, and all the jars work on the classpath with java -jar test.jar
.
I inspected the jar contents with jar xf test.jar
, and found that the jars are exactly the same, except for the manifests (see below):
Manifest-Version: 1.0
Created-By: 9.0.1 (Oracle Corporation)
Main-Class: test.Main
and
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: testuser
Build-Jdk: 9.0.1
Main-Class: test.Main
Notably, one still can't use java -p test.jar -m test
when specifying the working manifest:
$ 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>
Edit: A repo with the expected behavior: https://github.com/deontologic/test
I couldn't though find this in the jar
tool documentation precisely either, yet the jmod
tool defined it a little better.
--main-class class-name
Specifies main class to record in the module-info.class file.
I could further look into the JDK code and the behavior as you execute different commands seems related to the mainClass
attribute of the ModuleDescriptor.mainClass()
.
Since when packaging the jar with --main-class
flag, the entry in the module descriptor should be made to execute the module without specifying the fully qualified name of the main class during execution.
On the other hand this is not true using the maven jar creation and might be fixed in future upgrades as found by you as well.
More on why the following works :
java -jar test-1.0.0-SNAPSHOT-jar-with-dependencies.jar
If the -jar
option is specified, then its argument is the name of the JAR file containing class and resource files for the application. The startup class must be indicated by the Main-Class
manifest header in its manifest file(META-INF/MANIFEST.MF
)
and pretty obvious why specifying the fully qualified name works as:
java -p target/test-1.0.0-SNAPSHOT-jar-with-dependencies.jar -m test/test.Main
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With