How can I set the ModuleMainClass attribute of a J

2020-07-24 04:35发布

问题:

I'm using Gradle (6.0.1) with the moduleplugin to build an application out of JPMS modules using JDK 13.

However, even with the application plugin applied & its mainClassName set it does not set the ModuleMainClass attribute in module-info.class, so when I jlink it up into a standalone JVM and run java -m mymodule I get this message:

module mymodule does not have a ModuleMainClass attribute, use -m <module>/<main-class>

Digging under the hood it looks like the moduleplugin doesn't change the jar task at all, and the out of the box gradle jar task does not actually use the JDK's jar command, it just zips everything up itself.

As far as I can tell the only way to set the ModuleMainClass attribute in module-info.class is to use the JDK's jar command as so: jar --main-class=CLASSNAME -C <classes dir>.

Is there a way to do this, short of writing my own gradle task? And if not, has anyone got an example of replacing the gradle jar task with one that calls the JDK command?

(Please note this question is not about setting the Main-Class in the jar's MANIFEST.MF - that's easy, but isn't respected when calling java -m <modulename>.)

回答1:

It looks like the jar task in gradle does not do a proper job of building the jar to also include the module-main-class in the module-info.class. In fact it doesn't look like it calls the jar command at all which is a bit misleading. So here is an updated version that does this:

jar {
    doLast {
        project.exec {
            workingDir destinationDirectory.get()
            executable 'jar'
            args '--update'
            args '--file', archiveFileName.get()
            args '--main-class', mainClassName
            args '.'
        }
    }
}

Jar command syntax taken in part from this tutorial.

This looks janky, but it works and hopefully some day the Jar task will include that last part.