JPMS modularity and module – an introduction

1. Introduction

Java 9 introduced a new module system that makes modularization of applications easier. Java 9 modularity is built on top of the abstractions Java already has for encapsulations. Introduction of modules in Java 9 was a very big change as it resulted changes in JVM, the standard libraries and in the Java language itself.

This change is not an enhancement or introducing a new feature in Java language like streams. Java 9 module system is related the design, structure, compilation, packaging and deployment of application and so on.

2. Modularity

Modularization is the act of decomposing a system into self-contained but interconnected modules. JPMS stands for Java Platform Module System. Modularity adds a higher level of aggregation above packages. In terms of Java language, a module is a uniquely named group of packages, as well as resources(such as XML files and images) and a module descriptor. A module descriptor provides the following information about the module:

  • the module’s name
  • the module’s dependencies (i.e. the other module this module depends on)
  • the packages it explicitly makes available to other modules
  • the services it provides
  • the services it consumes
  • the other modules to which it allows reflection

Module is similar to a jar file as both are a group of packages. The difference between the two is that module contains metadata, i.e. configuration information.

The configuration information of module should be specified in a special file named with module-info.java. Every module should have module-info.java, otherwise JVM won’t consider that as a module of Java 9 platform.

3. History

The Java Module System was initially being developed under the Java Community Process as JSR 277 and was scheduled to be released with Java 7. JSR 277 later was put on hold and Project Jigsaw was created to modularize the JDK. This JSR was superseded by JSR 376 (Java Platform Module System). The Java SE platform is now modularized in Java 9.

4. Goals of modularizing Java

According to JSR 376, the key goals of modularizing the Java SE platform are:

  • Reliable configuration – Modules define explicit dependencies which are known at compile time and execution time, application knows what it requires to run.
  • Strong encapsulation – Modules explicitly state what packages they are making available(exports) for other modules. All packages which are not explicitly exported by a module become unavailable for other modules by default. This improves design and less surface area for attackers to attack.
  • Scalable Java platform – Previously, Java was a monolith consisting of everything in one structure. The pre-Java 9 runtime may be a Java Runtime Environment (JRE) or a Java Development Kit (JDK), but in both cases it includes rt.jar (runtime library), which contains the classes of the Java standard library. The platform is now modularized into 98 modules . You can create custom runtimes consisting of only modules you need for your apps or the devices you’re targeting.
  • Greater platform integrity – Since internal APIs are now more encapsulated, applications can not use these APIs. Previously applications had access to platform related APIs even if they didn’t suppose to. This has lead to greater platform integrity.
  • Improved performance – The JVM’s optimization techniques are more effective when it knows where to find what. Modules help this by providing information about dependencies and interfaces with other modules.

5. Java is modularized

Java is itself modularized into 98 modules. Following are few of the modules:

  • java.base
  • java.compiler
  • java.desktop
  • java.logging
  • java.se
  • java.se.ee
  • java.sql
  • java.xml
  • jdk.net

The JDK in Java 9 is no more a monolithic library. Each platform module defines a well-defined functionality of JDK like SQL and logging support.
The Java module system does not allow compile-time circular dependencies between modules.

You can inspect the module declarations of modules with --describe-module. For example:

java --describe-module java.base

6. Get list of platform modules

You can get the full list of platform modules by running

java --list-modules

The most essential platform module in the modular JDK is java.base. This module exposes packages such as java.lang and java.util, which are required by every other module. So we can say that every module requires java.base implicitly.

7. Get module of a class

We can find module of a class by using getModule() method.

public class ModuleExample {
    public static void main(String[] args) {
        System.out.println(String.class.getModule());// module java.base