From the quick start tutorial of project Jigsaw, it seems that module-info.java goes to a directory with the name of the module, for instance, for a module my.module containing a class MyClass:
bin/
my.module/
module-info.class
my/
module/
MyClass.class
Then, still following the tutorial, when calling MyClass (supposing it has a method
), the module-path option is given the bin
directory:
java -p path/to/bin -m my.module/my.module.MyClass
So far, so good.
However, it works also if I write:
java -p path/to/bin/my.module -m my.module/my.module.MyClass
And I don't understand why both work.
It makes no difference if bin
contains two modules: if both directories are in module path, the second version still works (and if only bin
is in module path, it works too, as documented in the tutorial).
Now, when I try to create a Maven project with Eclipse, using Java 9 modules, the module-info.java resides in the src/man/java
directory, and likewise module-info.class is in target/classes
. So now the directory containing the module-info.class file has no relation with the name of the module.
And target/classes
is also in the module path (when I check the build configuration). That's similar to the second case above, with java -p path/to/bin/my.module -m my.module/my.module.MyClass
.
So, apparently, Java uses only the contents of module-info.class to discover the module name, and the directory name is arbitrary?
But then, in the first case, when I write java -p path/to/bin -m my.module/my.module.MyClass
, it means Java will look in directories inside the directory in the module path.
I feel I am missing something important. Is there a clear explanation of the way Java looks for modules in directories in the module path? And what really specifies a module? (my impression is: not the directory, only module-info.java).
To add to my confusion: Oracle documentation states that:
--module-path modulepath... or -p modulepath
A semicolon (;) separated list of directories in which each directory is a directory of modules.
But apparently it's not all the story, and at least it's not how Eclipse uses with this option.
Note: I have seen this question, but it doesn't really help: one answer says module-info.java goes in src/java/, another says it goes to a directory whose name is the module name. Apparently both are correct, but they don't explain why, and there is an apparent contradiction.
From the documentation of java.lang.module.ModuleFinder#of(Path...)
:
Returns a module finder that locates modules on the file system by searching a sequence of directories and/or packaged modules. Each element in the given array is one of:
- A path to a directory of modules.
- A path to the top-level directory of an exploded module.
- A path to a packaged module.
The module finder locates modules by searching each directory, exploded module, or packaged module in array index order. It finds the first occurrence of a module with a given name and ignores other modules of that name that appear later in the sequence.
If an element is a path to a directory of modules then each entry in the directory is a packaged module or the top-level directory of an exploded module [emphasis added]. It is an error if a directory contains more than one module with the same name. If an element is a path to a directory, and that directory contains a file named
module-info.class
, then the directory is treated as an exploded module rather than a directory of modules [emphasis added].The module finder returned by this method supports modules packaged as JAR files. A JAR file with a
module-info.class
in its top-level directory, or in a versioned entry in a multi-release JAR file, is a modular JAR file and thus defines an explicit module. [...][...]
When you use --module-path path/to/bin
the path entry is treated as a directory of modules. This is because there is no module-info.class
file present in the bin
directory (i.e. top-level directory).
my.module
directory to anything you want; the ModuleFinder
simply looks at the directory to see if there's a module-info.class
file present.When you use --module-path path/to/bin/my.module
the path entry is treated as an exploded module. This is because there is a module-info.class
file present in the my.module
directory (i.e. top-level directory).
target/classes
directory is an exploded module because the module-info.class
file is present in the top-level directory.Unfortunately I was unable to find anything stating the above ModuleFinder
implementation is guaranteed to be used internally when executing java
. However, in all likelihood the above is what's used.