Java 9 Modules - Automatic Modules

[Last Updated: Aug 10, 2018]

In this tutorial, we will understand what Automatic Modules are and how they can help us to use a non-modular third party library jar in our modular application.

What are Automatic Modules?

Automatic Modules are named modules which are automatically created for a non-modular jar. It happens when the jar is placed on the 'module path' (as dependency) of a modular application.

In other words; non modular jar files become modular (automatic module) when used by a modular application.

Let's say we have a modular application 'app' (has the module-info.class) which wants to use a third party non-modular jar 'lib.jar' (does not have the module-info.class). If we run a main class of 'app' say using following command:

java --module-path appClasses;lib --module app/

then lib.jar (placed under lib folder) automatically becomes modular for 'app'. This module has the same name as the jar name (extension is dropped, hyphens '-', if any, are replaced by dots '.' and version part, if any, is also dropped). The module 'app' has to still explicitly import the jar module by its name using 'requires' clause in

In above command, appClasses is the folder where 'app' has its complied classes and lib is the folder where we have the third party lib.jar.

Automatic Modules are another migration tool which helps us to develop a modular application or modularize our existing applications without waiting for the third party libraries to become modularized.

What packages it 'exports'?

It 'exports' all its packages.

What modules it 'requires'?

It 'requires' all other modules on the module path.


This example will create two application. The first application will represent a non-modular third party library and the second one will be a modular application which will be using the first library .

The non-modular library


package easy.math;
public class BasicCalc {
  public static int sum(int a, int b) {
      return a + b;
D:\automatic-module-example\easy-math>tree /F /A

Compiling the class:

D:\automatic-module-example\easy-math>javac -d out src/easy/math/

Creating the jar:

D:\automatic-module-example>jar --create --file easy-math.jar -C easy-math/out .

The modular application

package com.example;

import easy.math.BasicCalc;

public class AppMain {
  public static void main(String[] args) {
      int sum = BasicCalc.sum(4, 7);
      System.out.println("sum : " + sum);

module {
 requires easy.math;

Note that above module declaration requiring the dependency jar module (automatic) by it's name which will transform from 'easy-math.jar' to 'easy.math'

D:\automatic-module-example\>tree /F /A

Moving easy-math.jar (from first project) to application:

D:\automatic-module-example>move easy-math.jar\lib\
1 file(s) moved.

Now here's our directory structure

D:\automatic-module-example>tree /F /A
| |
| +---out
| | \---easy
| | \---math
| | BasicCalc.class
| |
| \---src
| \---easy
| \---math
| easy-math.jar

Compiling the application:

D:\automatic-module-example\>javac --module-path lib -d out src/ src/com/example/

Running the application

D:\automatic-module-example\>java --module-path out;lib --module
sum : 11

Using jdeps

D:\automatic-module-example\>jdeps --module-path lib;out -s --module -> easy.math -> java.base

Using --describe-module

For the library jar:

D:\automatic-module-example\>jar --file lib\easy-math.jar --describe-module
No module descriptor found. Derived automatic module.

easy.math automatic
requires java.base mandated
contains easy.math

For the client application:

D:\automatic-module-example\>java --module-path out;lib\easy-math.jar --describe-module file:///D:/automatic-module-example/
requires easy.math automatic
requires java.base mandated
contains com.example

Creating jar of the main application

Let's convert our main application to jar as well and try --describe-module on the jar:

D:\automatic-module-example\>jar --create --file lib\math-app.jar -C out .
D:\automatic-module-example\>jar --file lib\math-app.jar --describe-module jar:file:///D:/automatic-module-example/!module-info.class
requires easy.math
requires java.base mandated
contains com.example

Using Module API

Let's use new Module API to analyze the modules.

package com.example;

import easy.math.BasicCalc;

public class ModuleAnalysis {

  public static void main(String[] args) {

  private static void analyze(Class<?> cls) {
      System.out.println("class: " + cls);
      Module module = cls.getModule();
      System.out.println("Module: " + module);
      System.out.println("Name: " + module.getName());
      System.out.println("isNamed: " + module.isNamed());
      System.out.println("Descriptor: " + module.getDescriptor());
      System.out.println("isAutomatic: " + module.getDescriptor().isAutomatic());

We just need to compile above class without recompiling the rest:

D:\automatic-module-example\>javac --module-path lib -d out src/com/example/
D:\automatic-module-example\>java --module-path out;lib --module
class: class com.example.ModuleAnalysis
Module: module
isNamed: true
Descriptor: module { name:, [easy.math, mandated java.base (@9)] }
isAutomatic: false
class: class easy.math.BasicCalc
Module: module easy.math
Name: easy.math
isNamed: true
Descriptor: module { name: easy.math, [mandated java.base] }
isAutomatic: true

How automatic module name is derived?

From ModuleFinder doc:

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.
  • The version, and the module name when the attribute "Automatic-Module-Name" is not present, are derived from the file name of the JAR file as follows:
    • The ".jar" suffix is removed.
    • If the name matches the regular expression "-(\\d+(\\.|$))" then the module name will be derived from the subsequence preceding the hyphen of the first occurrence. The subsequence after the hyphen is parsed as a Version and ignored if it cannot be parsed as a Version.
    • All non-alphanumeric characters ([^A-Za-z0-9]) in the module name are replaced with a dot ("."), all repeating dots are replaced with one dot, and all leading and trailing dots are removed.
    • As an example, a JAR file named "foo-bar.jar" will derive a module name "" and no version. A JAR file named "foo-bar-1.2.3-SNAPSHOT.jar" will derive a module name "" and "1.2.3-SNAPSHOT" as the version.

Example Project

Dependencies and Technologies Used:

  • JDK 9
Java 9 Automatic Example Select All Download
  • automatic-module-example
    • easy-math
      • src
        • easy
          • math
      • src
        • com
          • example

    See Also