javajava-modulemodule-path

In which directory does module-info.java go?


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.


Solution

  • 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:

    1. A path to a directory of modules.
    2. A path to the top-level directory of an exploded module.
    3. 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. [...]

    [...]

    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.