Close

Java 9 Modules - The Unnamed Module

[Last Updated: Aug 9, 2018]

In this tutorial, we will understand what Unnamed module is and how it helps the old code to continue working in Java 9.

What is Unnamed module?

A class which is not a member of a 'named module' is considered to be a member of a special module known as the unnamed module. The unnamed module concept is similar to the unnamed package (the default package). The unnamed module is not a real module. It can be considered as the default module which does not have a name.

All classed compiled in Java 8 and older versions, which are not yet migrated to modules, also belong to the unnamed module when run in Java 9.

What modules it 'requires'?

The unnamed module 'requires' every other named modules automatically.

That means all classes within the unnamed module can read all other module (named or unnamed) without any explicit declaration of any kind. That also means that older classes (written prior to Java 9) can read all modules defined by the new Module system. Hence, all such classes will continue to compile and run in Java SE 9 without any modification.

What packages it 'exports'?

The unnamed module 'exports' all its packages.

That means different Jar applications which do not contain module or which are compiled in the older versions, will continue to use each other's dependencies as it is.

The packages exported by unnamed module can only be read by another unnamed module. It is not possible that a named module can read (requires) the unnamed module. Of course, to explicitly use 'requires' clause in a module-info.java or use a command line option to add the module, we need a module name.

Example

Let's create a very simple project without a module.

D:\unnamed-modules-example>tree /F /A
\---src
\---com
\---logicbig
UnnamedTest.java

unnamed-modules-example/src/com/logicbig/UnnamedTest.java

public class UnnamedTest {
  public static void main(String... st) {
      Module module = UnnamedTest.class.getModule();
      System.out.println("Module: "+module);
      System.out.println("Name: " + module.getName());
      System.out.println("isNamed: " + module.isNamed());
      System.out.println("Descriptor: " + module.getDescriptor());
  }
}

In above example, we used the new method java.lang.Class#getModule() which returns an instance of java.lang.Module (also introduced in Java 9). The returned instance of the Module represents a module that this class is a member of. The method Module#getDescriptor() returns an ModuleDescriptor object which typically represents details of module-info.class. Other methods we used above are self-explanatory.

Output

Module: unnamed module @7c75222b
Name: null
isNamed: false
Descriptor: null

The above output is taken from IntelliJ.

Let's use javac/java and other tools to learn unnamed modules behavior closely.

D:\unnamed-modules-example>javac -d out src/com/logicbig/UnnamedTest.java
D:\unnamed-modules-example>java -cp out com.logicbig.UnnamedTest
Module: unnamed module @224aed64
Name: null
isNamed: false
Descriptor: null

Unnamed module vs class path/module path

Note that in above example, we used class path instead of module path. If we want to run our old code without migrating to new module system then they should be run using class path only.

In above example, can we use module path to run our main class? Let's consider the following possible command:

    java --module-path out -module moduleName/com.logicbig.UnnamedTest

What we are going to use for moduleName above? We don't have a name in this case. That means, we cannot run unnamed modules on module path.

Using jdeps

This tool was introduce in Java 8. It is a class/jar dependency analyzer. It's been enhanced for Java 9 modules. Let's use it on our 'out' folder:

D:\unnamed-modules-example>jdeps -s out
out -> java.base

Our code requires only java.base. As mentioned above, the unnamed module requires every other named modules automatically. But why don't we see all named modules of JSE 9 in above output, that's because they are imported on demand, i.e. only when we use them. Let's use another class which is not in java.base.

unnamed-modules-example/src/com/logicbig/UnnamedTest2.java

package com.logicbig;

import java.util.logging.Logger;

public class UnnamedTest2 {
  private static final Logger log = Logger.getLogger(UnnamedTest2.class.getName());
  public static void main(String... st) {
      Module module = UnnamedTest2.class.getModule();
      log.info(module.toString());
  }
}
D:\unnamed-modules-example>javac -d out2 src/com/logicbig/UnnamedTest2.java
D:\unnamed-modules-example>java -cp out2 com.logicbig.UnnamedTest2
Sep 30, 2017 3:31:40 AM com.logicbig.UnnamedTest2 main
INFO: unnamed module @783e6358

Let's use jdeps

D:\unnamed-modules-example>jdeps -s out2
out2 -> java.base
out2 -> java.logging

This time, our compiled class under out2 folder uses java.logging module as well.

Using --describe-module

--describe-module <module name> is a java command option, which describes a module details. Since the unnamed module does not have a name we cannot use this option.

jar command also has --describe-module option which does not require a module name. It describes the module in the specified jar. Let's create a jar of our above example and use this option.

D:\unnamed-modules-example>jar --create --file my-lib.jar -C out/ .

Let's run our main class first to see our jar is working properly:

D:\unnamed-modules-example>java -cp my-lib.jar com.logicbig.UnnamedTest
unnamed module @1c2c22f3

Now use '--describe-module' option

D:\unnamed-modules-example>jar --file my-lib.jar --describe-module
No module descriptor found. Derived automatic module.

my.lib automatic
requires java.base mandated
contains com.logicbig

The above output says 'No module descriptor found'. An unnamed module does not have a descriptor. We also saw that in our first example output. As an unnamed module does not have module-info.java, there's no ModuleDescriptor object for them.

The output also says 'Derived automatic module'. An automatic module is a different type of module. This part of description is applied in a different context. Here context refers to whether we run our jar either using class path or using module path. Above automatic module description is applied when we use module path. We will learn about automatic module in a coming tutorial.

Summary

  • The unnamed module does not have module-info.java.
  • Or in other words, the classes which do not have modules are promoted to the unnamed module.
  • The unnamed module 'requires' all other modules and 'exports' all its packages.
  • The classes which were written in the older versions but now running in Java 9 environment will continue to work because they become the members of the unnamed module.
  • If we want to run old code in Java 9 environment without migrating them to the module system, we should run them using class path (not module path)

Example Project

Dependencies and Technologies Used:

  • JDK 9
Java 9 Unnamed Module example Select All Download
  • unnamed-modules-example
    • src
      • com
        • logicbig
          • UnnamedTest.java

    See Also