Discussion:
Main class in jar
Bernard Amade
2018-03-05 09:54:41 UTC
Permalink
Hello all
the doc in https://docs.oracle.com/javase/9/docs/specs/jar/jar.html
lists for Main-Class entry in jars:
"attribute defined for stand-alone applications: This attribute is used by stand-alone applications that are bundled into executable jar files which can be invoked by the java runtime directly by running "java -jar x.jar".
apparently it means that you should not create a modular jar with a manifest template containing a Main-Class entry
(apparently if you run the app with command "java -module-path dir -m com.thing.app" with the generated com.thing.app.jar the main class will not be found : you get a message saying you've got no Mainclass atrribute)
but if you generate the jar with a manifest template with no Main-Class entry and instead use the --main-class option then the main class will be found.
funnily the MANIFEST-MF will then have the same Main-Class entry!
so what is the difference?
(btw I suggest more docs that differentiate clearly what to do
1) with non-modular jars
2) with modular jars ..
... or is it I can't read the doc properly?)

thanks
Bear
Alan Bateman
2018-03-05 10:25:08 UTC
Permalink
Post by Bernard Amade
Hello all
the doc in https://docs.oracle.com/javase/9/docs/specs/jar/jar.html
"attribute defined for stand-alone applications: This attribute is used by stand-alone applications that are bundled into executable jar files which can be invoked by the java runtime directly by running "java -jar x.jar".
apparently it means that you should not create a modular jar with a manifest template containing a Main-Class entry
(apparently if you run the app with command "java -module-path dir -m com.thing.app" with the generated com.thing.app.jar the main class will not be found : you get a message saying you've got no Mainclass atrribute)
but if you generate the jar with a manifest template with no Main-Class entry and instead use the --main-class option then the main class will be found.
funnily the MANIFEST-MF will then have the same Main-Class entry!
so what is the difference?
The error message with JDK 9 and JDK 10 has a typo which may be causing
confusion here. The typo has been fixed for JDK 11 via JDK-8193819 to
correctly say "ModuleMainClass" attribute. Note that this is a class
file attribute, not an attribute that you put in the main manifest of a
JAR file. The `jar` tool will add both when you specify the main class
with `--main-class` or `-e`.

To summarize:

1. `jar -jar app.jar` is the equivalent of `java -cp app.jar
<mainclass>` where <mainclass> is value of the Main-Class attribute in
the main manifest of the JAR file.

2. `java [--module-path <path>] -m <app>` is the way to run a modular
application on the command line. The app module must have a
ModuleMainClass class file attribute, something the `jar` tool will do
for you (Maven plugins and IDEs should do the same but might not be all
there yet).  The alternative is `-m app/<mainclass>` which you specify
both the initial/main module and also its main class.

3.  There is no support for executing modular applications with `java -jar`.

-Alan
Alan Bateman
2018-03-05 11:05:22 UTC
Permalink
thanks for your help
---------------------------------------------------
"ModuleMainClass" attribute. Note that this is a class file attribute, not an attribute that you put in the main manifest of a JAR file. The `jar` tool will add both when you specify the main class with `--main-class` or `-e`.
The app module must have a ModuleMainClass class file attribute, something the `jar` tool will do for you
----------------------------------
where does this "ModuleMainClass" attribute lies internally?
(I've tried to decompile almost every file but have not found it)
It's an attribute in the module-info.class. You can use `javap` to see
all the details if you want, e.g.
  javap --module-path app.jar -m app -v module-info

The `jar` tool might be easier for your audience, e.g.
  jar --file=app.jar --describe-module
PS: if I understand things correctly the reason for not having an autonomous jar (like in java -jar) is that
starting a modular application from jars needs a lot of specific command-line options ....
Do we really have to stick to shell scripts to start an app? (when we do not go for a jlink generated image)
If the initial module is not in the run-time image then you have to
specify the module path so that the module can be found. Re-purposing
`java -jar` was discussed here but for the initial release at least,
`java -jar ...` will put the JAR file on the class path as it has always
done. It's also related to the #MultiModuleExecutableJARs issue where
there is interest in packaging an initial module, along transitive
dependences, in a single JAR file. So I expect this area will be
revisited at some point.

-Alan
Gregg Wonderly
2018-03-05 13:58:23 UTC
Permalink
Will java -jar note that the argument is a module and help the user understand how to invoke it, or will it just complain about a missing main-class: attribute? From a practical perspective, why does it matter and demand a different command line? What happens when you double click on a module?

Gregg

Sent from my iPad
Post by Bernard Amade
Hello all
the doc in https://docs.oracle.com/javase/9/docs/specs/jar/jar.html
"attribute defined for stand-alone applications: This attribute is used by stand-alone applications that are bundled into executable jar files which can be invoked by the java runtime directly by running "java -jar x.jar".
apparently it means that you should not create a modular jar with a manifest template containing a Main-Class entry
(apparently if you run the app with command "java -module-path dir -m com.thing.app" with the generated com.thing.app.jar the main class will not be found : you get a message saying you've got no Mainclass atrribute)
but if you generate the jar with a manifest template with no Main-Class entry and instead use the --main-class option then the main class will be found.
funnily the MANIFEST-MF will then have the same Main-Class entry!
so what is the difference?
The error message with JDK 9 and JDK 10 has a typo which may be causing confusion here. The typo has been fixed for JDK 11 via JDK-8193819 to correctly say "ModuleMainClass" attribute. Note that this is a class file attribute, not an attribute that you put in the main manifest of a JAR file. The `jar` tool will add both when you specify the main class with `--main-class` or `-e`.
1. `jar -jar app.jar` is the equivalent of `java -cp app.jar <mainclass>` where <mainclass> is value of the Main-Class attribute in the main manifest of the JAR file.
2. `java [--module-path <path>] -m <app>` is the way to run a modular application on the command line. The app module must have a ModuleMainClass class file attribute, something the `jar` tool will do for you (Maven plugins and IDEs should do the same but might not be all there yet). The alternative is `-m app/<mainclass>` which you specify both the initial/main module and also its main class.
3. There is no support for executing modular applications with `java -jar`.
-Alan
Alan Bateman
2018-03-05 15:40:29 UTC
Permalink
Post by Gregg Wonderly
Will java -jar note that the argument is a module and help the user understand how to invoke it, or will it just complain about a missing main-class: attribute? From a practical perspective, why does it matter and demand a different command line? What happens when you double click on a module?
`java -jar` has not changed,  it will print an error to say that there
is "no main manifest attribute" as it has always done.

If your modules aren't in the run-time image then you have to specify a
module path to the java launcher. This is different to `java -jar` where
you've packaged everything into a single JAR file (ignoring Class-Path
in the this discussion for now). As I said, there is a carry over issue
from JSR 376 to examine the topic of executable modular "uber JARs" so I
expect it will be re-examined.

I assume by "double on a module" then you mean a JAR file. In that case
it depends on how your desktop is configured. Some users may have it
configured to run "javaw.exe" with `-jar %1` as the parameters, this
would be the equivalent of typing `java -jar ...` on the command line.

-Alan
Gregg Wonderly
2018-03-05 22:30:42 UTC
Permalink
But since jar vs module both require a manifest entry or command-line argument to specify the exact thing to “run”, can’t they both inspect the opportunity to act like the other form of command line, and then do the right thing?

The problem is that “uber JARs” (which I have used for decades at this point), used as “applications”, being doubled clicked on, will require there to be this inspection and intelligent execution.

I feel its really important to make this seamless so that people who really do use java as a desktop application environment can provide a single jar to allow users to use the application. Installers are just not something that we need to start the path to have to support cross platform…

Gregg
Post by Gregg Wonderly
Will java -jar note that the argument is a module and help the user understand how to invoke it, or will it just complain about a missing main-class: attribute? From a practical perspective, why does it matter and demand a different command line? What happens when you double click on a module?
`java -jar` has not changed, it will print an error to say that there is "no main manifest attribute" as it has always done.
If your modules aren't in the run-time image then you have to specify a module path to the java launcher. This is different to `java -jar` where you've packaged everything into a single JAR file (ignoring Class-Path in the this discussion for now). As I said, there is a carry over issue from JSR 376 to examine the topic of executable modular "uber JARs" so I expect it will be re-examined.
I assume by "double on a module" then you mean a JAR file. In that case it depends on how your desktop is configured. Some users may have it configured to run "javaw.exe" with `-jar %1` as the parameters, this would be the equivalent of typing `java -jar ...` on the command line.
-Alan
Loading...