user10307643
user10307643

Reputation:

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.

Upvotes: 3

Views: 3347

Answers (1)

Slaw
Slaw

Reputation: 46146

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. [...]

[...]

  • 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).

    • As far as I can tell, there's no requirement that any exploded module within the directory of modules needs to have a top-level directory whose name matches the name of the module. It's simply a convention. In other words, you could rename your 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).

    • The same is true when using a build tool such as Maven. The 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.

Upvotes: 2

Related Questions