Architecture & DesignWhat Is the Java 9 Module System?

What Is the Java 9 Module System?

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

The flagship feature of Java 9 is Project Jigsaw. The objective is to incorporate modularity from the core of the Java platform. Java, so far, is not much modularized in its core architecture and from there arises numerous problems when one tries to incorporate it externally. The JDKs and JREs were primarily monolithic artefacts. So, to modularize Java, the team had to rethink a large part of it design. But, the problem is that during these years, Java became a reliable platform for numerous business critical applications. It is not possible to reinvent Java without considering the legacy applications and backward compatibility. Therefore, a double effort is required to keep the equilibrium of the Java ecosystem intact and, at the same time, revamp it to incorporate much-needed changes. Modularization has many benefits, such as: leveraging productivity, ease of maintenance, being conducive to the evolution of software system, and so forth. This article provides an overall picture of the module system as incorporated in Java 9.

Modules in a Nutshell

The word module came from a popular software design technique called Modular Programming. This technique emphasizes the fact that a program should be built as an individual component with distinct functionality in a manner that these individual components can be combined to create a useful program. A module is simply a unit of this programming paradigm. Typically, it means a distinct unit of software that may be built individually, but can be used as a unit of construct for a more complex system. It is reusable, decoupled, and has an identity with a separate concern.

The reason to make a system modular is twofold: to simplify a complex system and leverage productivity.

According to Java Specification Lead, Mark Reinhold, a module in Java is a named, self-describing collection of code and data in the form of a type (classes and interfaces). Until Java 8, packages were the highest level of aggregation possible, but Java 9 introduced a new language element called a module. This is basically a named group of packages that can be reused like a resource. Every module has a module descriptor, a metadata specifying the following items:

  • Name of the module
  • Services offered by this module
  • Services consumed by this module
  • The reflection it allows to other modules
  • Dependencies it has on other modules
  • Specification of the list of packages that are publicly exported to other modules as module APIs

It is basically a compiled version of the module description containing its attributes. The naming scheme is similar to a compiled class file created from the package declaration, such as module-info.java, that echoes package-info.java.

Goals of Modularization

Java 9 emphasizes the following four aspects as its primary objective of strengthening Java:

  • Strong Encapsulation: Java has no mechanism to establish encapsulation at the package level. Java 9 establishes that packages in a module are accessible only to other modules if and only if the said module explicitly exports them.
  • Reliable Configuration: With Java 9, a module configuration can be established that can be walked through to determine the subset of dependent modules both at compile time and execution time by a Java application.
  • Scalable: The days of JRE as a monolithic artefact is a day of the past. JRE is modularized into several modules. One can pick the required modules and create a sleek custom runtime according to the specific need of a particular application. Therefore, the Java platform is itself now scalable.
  • Improved Performance: Java 9 has been improved

Module Declaration in Java 9

According to the Java Specification (JSR 379), packages may be grouped into modules that serve as building blocks in the construction of a very large problem. The declaration of a module specifies which other modules are required o compile and run code in its own packages.

Typically, a module is declared as follows:

module moduleA{

   requires moduleB;
   requires transitive moduleC;
   requires static moduleD;

   exports moduleE;
   exports moduleF to moduleG, moduleH;

   opens package1;
   opens package1 to package2,package3;

   uses MyInterfaceImpl;

   provides MyClassService1 with MyClassService2;
}

A module declaration body may contain zero or more module directives, as stated in the preceding example. When this file is compiled, Java creates a file called module-info.class in the module root directory.

A Quick Look at the Module Declaration Directives

  • The requires directive establishes dependency relationship. Here, it means that moduleA is dependent on moduleB. The transitive directive specifies a transitive dependency relationship, such as in the previous example, moduleA states a transitive dependency with moduleC; this means that any module that reads moduleA will also be able to read implicitly moduleC. The static directive states that the module is required at the time of compilation but is optional at the time of execution.
  • The exports module directive states that the module’s public type in the packages is accessible to all other modules. The exports…to module directive is used to specify exclusive accessibility to a comma-separated list of modules.
  • With the open directive, it is possible to specify the packages and its content types are accessible via reflection. The opens…todirective is used for the same purpose but exclusively to the selected list of modules. If, however, all the modules should be accessible at runtime via reflection, one may write:
    open module mymodule{
    
       // ... Module directives
    }
    
  • The uses directive is used to specify the services consumed by this module. A service in Java is provided by an instance of a class that extends an abstract class or implements an interface.
  • The provides…with directive is a juxtaposed directive of the uses directive in the sense that it specifies the services provided by this module.

A Glimpse into Changes in JRE

Java 9 divided JDK into modules to support various configurations. These include Java SE standard modules, JavaFX modules, JDK-specific modules, Oracle-specific modules, and so on. The structural changes will have direct impact on performance, security, and maintainability of the project targeted to run on Java 9 platform. Apart from these, the JRE is going to directly affect the application behaviour during execution. In most cases, the application developer is unaffected by the changes and need not bother with them. But, for the developers who create applications that directly interact with the core system, there will be a direct impact from the changes.

All Java SE module names are prefixed by ‘java’. Here is the complete list of modules as stated in the Specification:

java.activation
java.base
java.compiler
java.corba
java.datatransfer
java.desktop
java.instrument
java.logging
java.management
java.management.rmi
java.naming
java.prefs
java.rmi
java.scripting
java.se
java.se.ee
java.security.jgss
java.security.sasl
java.sql
java.sql.rowset
java.transaction
java.xml
java.xml.bind
java.xml.crypto
java.xml.ws
java.xml.ws.annotation

Conclusion

The Java Module System was actually proposed in 2005 (JSR 277) to be a part of Java 7. This was later superseded by the Java Platform Module System (JSR 376) and was supposed to be a part of Java 8. The enormity of this project and the changes it would bring on the existing system had to be verified time and again to avoid catastrophe. This is one of the reasons for its slated release. As we dive deeper, there are more intricacies involved with Java Module System and we are going to unravel them in subsequent articles. So stay tuned.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories