Java 9 Modules - Automatic Modules

[Updated: Oct 15, 2017, Created: Sep 30, 2017]

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

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