Modularization is one of the most important of java 9 features. In this article, we are going to understand java 9 modules, its benefits, how to create a module with practical examples.

JPMS
JPMS stands for Java Platform Module System. It is a new feature introduced in java 9 for promoting modular programming in java.
It is also known as Project Jigsaw.
What is a Module?
A module is a collection of packages containing compiled class files and can be considered as an executable unit.
It is similar to a jar file which also contains a bunch of packages. But, there are two differences between a module and jar.

  1. A module contains a file known as module-info.java. This file contains some information about a module. Don’t worry, covered later in this post.
  2. All classes in a module should be inside some package unlike a jar in which classes can be in no (or default) package.
    If they are not, then the module will not compile.

Starting java 9, the concept of jar files is gone. It is replaced by modules.
Even the compiled classes of java library are also available as modules. All standard java packages are now modules.

In java 9 java.lang package is replaced by java.base module; java.sql package is replaced by java.sql module and so on.

If you notice the folder structure of jdk 9, there is a folder named jmods which contains all the modules of standard java library as shown below.

modules in java 9

Just as java.lang package was imported by default in earlier java versions, java.base module is imported by default starting java 9.


Benefits of Modules

  • Better Scalability
    Making the application modular decreases its size thus making it more scalable.
    Prior to java 9, even for executing a simple program for printing “Hello World”, all java classes were required in the form of rt.jar  though it required only a few classes.
    Now there is no need for unnecessary classes which will never be used.
  • Improved Security
    Prior to java 9 or modules, there was no way to control visibility of a package outside the jar.
    If you add a package, all the classes inside the package will be visible to outside world, no matter if you created it for internal use only.
    With modules, you can control the visibility of packages inside a module so that other modules cannot access it.
  • Reduced risk of NoClassDefFoundError
    Before java 9, suppose your application relied on some jars for execution. If a jar or a single class is missing from the classpath, JVM will throw a NoClassDefFoundError whenever that class is required during execution.
    It doesn’t matter how many lines of code has already been executed. There was no way to check the presence of all required classes before execution.
    In java 9, JVM will check for the presence of all required modules before starting execution so that if any module is not present, it will not start execution.

module-info.java
This file is the primary requirement for a group of packages to be considered as a module.
It can be considered as the identity of a module. If this file is not present java compiler will not consider the packages as module.
Each module has its own module-info.java file and it contains following information about the module:

  1. Name of the module which contains this file. Name is specified after module keyword.
  2. What packages this module expose to other modules using exports keyword. This is used to achieve security benefit outlined above.
  3. What other modules are required by this module for proper execution using requires keyword.
    This information is used by the JVM to prevent NoClassDefFoundError in the middle of execution.

module-info.java is checked before execution to check for the presence of all required modules.

A typical structure of module-info.java is as below.

module demomodule {
  requires depmodule1;
  requires depmodule2;

  exports package1;
  exports package2;
}

Here, demomodule is the name of module. This should match the folder name which contains module-info.java file.

requires specifies the modules which this module requires for compilation and execution.
exports specifies the packages which are exposed outside.

requires and exports sections are optional and are only required when the module is exporting some packages or needs other modules for its execution.

Remember that requires should be followed by modules and exports should be followed by packages.

How to create a module?
Module creation is not a special process but you need to perform some extra steps apart from normal coding procedure which was performed earlier.
First and most important is the creation of module-info.java file and organizing your code as per the module creation guidelines.
Imagine earlier your java code files were organized as

src
   |— com
              |— codippa
                               |— Main.java

Main.java file inside package com.codippa. Now, in order to package it as a module, you need to perform following steps:

  1. Move the entire package into a folder and name the folder as the name of the module. Name can be anything you want.
  2. Create a file named module-info.java directly inside the module folder and at the same level as your packages.

That’s it. You are ready with the module structure. The new folder structure will become as below.
Name of the module is codippaModule.

codippaModule
              |— module-info.java
              |— com
                       |— codippa
                                   |— Main.java  

Contents of module-info.java file for above module will be

module codippaModule {
}

This module is not exporting any package, neither does it require any other module for execution. Also note that the module name should match the folder name in which this file is present.

Compiling a module
In order to compile a module from command line using javac, there are some modifications as compared to conventional method.
Now you need to tell following to the compiler:

  1. The location of the module you need to compile using flag –module-source-path(starts with double hyphen)followed by the location.
  2. Location where the compiler should place the compiled module using flag -d followed by the location.
  3. A flag -m which indicates that we are compiling a module followed by the name of module we are compiling.
    We can also compile more than one modules at the same time.

Example, suppose the entire folder structure of a module(on Windows) is as below

F:
|— java9
|— src
|— codippaModule
                               |— module-info.java
                               |— com
                                       |— codippa
                                                 |— Main.java  

Open command prompt and navigate to the folder F:/java9 and type the following command.

javac –module-source-path src -d bin -m codippaModule

Above command tells the compiler that the location of module is the src folder, the destination of compiled module will be bin folder and the name of the module is codippaModule.
After this command executes, following will be the updated structure

F:
|— java9
bin
|— codippaModule
                             |— module-info.class
                             |— com
                                      |— codippa
                                                  |— Main.class
src
|— codippaModule
                             |— module-info.java
                             |— com
                                     |— codippa
                                                 |— Main.java  

Look, a bin folder is created as required with all the compiled class files.

Module Compilation Tweaks

Following points must be remembered when compiling a module

  • A module can be compiled using any of the following commands

    javac –module-source-path [modulePath] -d [compiledLocation] -m [moduleName] javac –module-source-path [modulePath] -d [compiledLocation] –module [moduleName]

  • If there is no module-info.java file inside the module folder, then the compiler will not consider it as a module. When trying to compile it using any of the above commands or using -m option, it will give an error as

    error: module codippaModule not found in module source path

  • Name of the module folder should match the name of the module in module-info.java file else the compiler will give an error

    error: module [moduleName] not found in module source path

  • Classes inside a module should be in some package. If a class has no package then compile will give an error
    src\module\Main.java:1: error: unnamed package is not allowed in named modules
    public class Main {
    ^
    1 error
  • -d flag to tell the compiler the location of compiled module is mandatory when compiling a module with -m flag. If not given, the compiler will give an error.

    error: class output directory must be specified if -m option is used

Executing or Running a module

Just as there is a separate method to compile a module, there is a new method to execute a module.
In order to execute a module following command is used

java –module-path [moduleLocation] -m [moduleName/Fully qualified name of class]

In our above example, where the whole folder structure is demonstrated, the command to execute Main.class will be

java –module-path bin -m codippaModule/com.codippa.Main

assuming we are in F:/java9 folder. Note that flag module-path starts with double hyphen.

Module Execution Tweaks

  • There should be a forward slash(/) between module name and class name to be executed.
    If you give the name of class as codippaModule\com.codippa.Main, then you will get an error like

    Error occurred during initialization of boot layer
    java.lang.module.FindException: Module codippaModule\com.codippa.Main not found

  • Location of compiled module can be relative or absolute. If it is relative, remember that it should start from the folder you are in.

Hope this post clarified the concept of modules in java 9, how they are beneficial, how to make a module, run a module and different points worth considering when creating modules.