What is an automatic module? What is an automatic module? java java

What is an automatic module?


I first answer your actual question ("What is an automatic module?"), but I also explain what they are there for. It is hard to understand why automatic modules behave the way they do without that information.

What is an automatic module?

The module system creates a module from every JAR it finds on the module path. For modular JARs (i.e. those with module descriptors) that is straightforward as they define the module's properties (name, requires, exports). For plain JARs (no module descriptor) this approach doesn't work, so what should the module system do instead? It automatically creates a module - an automatic module, so to speak - and takes the most safe guesses for the three properties.

Name

Deriving the name is a two-step process:

  • if the JAR defines the Automatic-Module-Name header in its manifest, it defines the module's name
  • otherwise, the JAR file name is used to determine the name

The second approach is intrinsically unstable, so no modules with a dependency on such an automatic module should be published. Maven warns about that.

Requires

Since a plain JAR expresses no requires clauses, the module system lets automatic modules read all other modules that make it into the readability graph (aka module graph). Unlike explicit modules, automatic ones also read the unnamed module, which contains everything that was loaded from the class path. This seemingly minor detail turns out to be very important (see below).

Automatic modules have some further readability quirks, though:

  • As soon as the first automatic module is resolved, so are all others. That means once a single plain JAR on the module path is referenced by another module, all plain JARs are loaded as automatic modules.
  • Automatic modules imply readability on all other automatic modules, which means a module reading one of them, reads all of them.

Taken together this can have the unfortunate effect that an explicit module (i.e. a non-automatic one) that depends on several plain JARs can get away with only requiring one of them (as long as the others end up on the module path as well).

Exports/Opens

Since the JAR contains no information which packages are considered public APIs and which aren't, the module system exports all packages and also opens them for deep reflection.

More

The module system also scans META-INF/services and makes the automatic module provide the services named therein. An automatic module is assumed allowed to use all services.

Finally, the Main-Class manifest entry is processed as well, so a plain JAR that defines one can be launched just like an automatic module where the main class was set with the jar tool (i.e. java --module-path my-app.jar --module my.app).

Proper module

Once the automatic module was created, it is treated as any other module. This explicitly includes that the module system checks it a any other module, for example for split packages.

What is an automatic module for?

One of the reasons for introducing modules was to make compiling and launching applications more reliable and find errors sooner that was possible with the class path. A critical aspect of that are requires clauses.

To keep them reliable, there is no way for a module declaration to require anything other than a named module, which excludes everything loaded from the class path. If the story ended here, a modular JAR could only depend on other modular JARs, which would force the ecosystem to modularize from the bottom up.

That is unacceptable, though, so automatic modules were introduced as a means for modular JARs to depend on non-modular ones and all you need to do for that is place the plain JAR on the module path and require it by the name the module system gives it.

The interesting bit is that because automatic modules read the unnamed module, it is feasible (and I generally recommend doing that) to leave its dependencies on the class path. This way automatic modules act as a bridge from the module to the class path.

Your modules can sit on one side, require their direct dependencies as automatic modules, and indirect dependencies can remain on the other side.Every time one of your dependencies turns into an explicit module, it leaves the bridge on the modular side and draws its direct dependencies as automatic modules onto the bridge.


An automatic module is a named module that is defined implicitly, since it does not have a module declaration. An ordinary named module, by contrast, is defined explicitly, with a module declaration; we will henceforth refer to those as explicit modules.

The primary benefit of using these is that they allow you to treat an artifact as a module when compiling or running without waiting for it to be migrated to the modular structure.

The module name of an automatic module is derived from the JAR file used to include the artifact if it has the attribute Automatic-Module-Name in its main manifest entry. The module name is otherwise derived from the name of the JAR file by the ModuleFinder.


Derived from the fact that the automatic module doesn't have a module declaration it's practically not feasible to tell what all modules or packages does it reads, opens or exports.

➜ So, since there are no explicit exports/opens for packages residing in the automatic module, described as -

.. no practical way to tell which of the packages in an automatic module are intended for use by other modules, or by classes still on the class path. Every package in an automatic module is, therefore, considered to be exported even if it might actually be intended only for internal use.

➜ Quoting the link further -

... no practical way to tell, in advance, which other modules an automatic module might depend upon. After a module graph is resolved, therefore, an automatic module is made to read every other named module, whether automatic or explicit.

The one of the proposals - An automatic module offers the traditional level of encapsulation: All packages are both open for deep reflective access and exported for ordinary compile-time and run-time access to their public types.


➜ Additionally, an automatic module

grants implied readability to all other automatic modules

due to the reason, that while using multiple automatic modules in a module its

..not feasible to determine whether one of the exported packages in an automatic module(x.y.z) contains a type whose signature refers to a type defined in some other automatic module(a.b.c).


(You do seem to be right about a missing complete definition as I didn't find it in the language or JVM specs)

The Javadocs provide a great deal of formal definitions though in the java.lang.module package classes.

Partial quote from https://docs.oracle.com/javase/9/docs/api/java/lang/module/ModuleFinder.html#automatic-modules:

A JAR file that does not have a module-info.class in its top-level directory defines an automatic module, as follows:

  • If the JAR file has the attribute "Automatic-Module-Name" in its main manifest then its value is the module name. The module name is otherwise derived from the name of the JAR file.

...

And from https://docs.oracle.com/javase/9/docs/api/java/lang/module/ModuleDescriptor.html:

The module descriptor for an automatic module does not declare any dependences (except for the mandatory dependency on java.base), and does not declare any exported or open packages. Automatic module receive special treatment during resolution so that they read all other modules in the configuration. When an automatic module is instantiated in the Java virtual machine then it reads every unnamed module and is treated as if all packages are exported and open.

EDIT (2021):

This section on module dependences from the Java Language Specification has the following interesting notes:

The Java SE Platform distinguishes between named modules that are explicitly declared (that is, with a module declaration) and named modules that are implicitly declared (that is, automatic modules). However, the Java programming language does not surface the distinction: requires directives refer to named modules without regard for whether they are explicitly declared or implicitly declared.

While automatic modules are convenient for migration, they are unreliable in the sense that their names and exported packages may change when their authors convert them to explicitly declared modules. A Java compiler is encouraged to issue a warning if a requires directive refers to an automatic module. An especially strong warning is recommended if the transitive modifier appears in the directive.