Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPMS/Jigsaw Missing Main Class in Module

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

like image 890
kantianethics Avatar asked Dec 19 '17 01:12

kantianethics


1 Answers

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
like image 133
Naman Avatar answered Oct 03 '22 18:10

Naman