Java platform module system

Java 9 introduced a new feature known as the Java platform module system (JPMS) or Java modules. It has been added to collect Java packages and code them into a single unit called a module.

In earlier versions of Java, there was no concept of modules which made it difficult to manage all the applications. To cater to that, Java 9 restructured JDK into a set of different modules so that developers can access only the required module for the project and not the whole JDK. Apart from JDK, Java now also allows developers to create modules for developing module-based applications.

 

In this article, we will be discussing what Java modules are and how to use them.

What is a Java module?

It is a packaging mechanism that allows developers to package a Java application or an API in separate Java modules. It is packaged as a modular JAR file where developers can also specify which of the Java packages inside a module should be visible to other Java modules.

Why should you use Java modules?

Using Java modules brings various benefits for Java developers. Following are some of the major advantages that make Java modules a great option for building applications,

1. Easier to distribute applications

JPMS splits up all Java platform APIs into separate modules. It lets developers specify what modules the application will require. With that information, Java can package your application including only the needed API Java modules.

Before JPMS, you would have had to package all of the APIs with your application. The unused APIs often made the application unnecessarily large and difficult to distribute.

2. Better encapsulation of internal packages

A Java module has to explicitly specify which Java packages inside the module can be visible to other Java modules users. The modules that are kept hidden can only be used internally inside the Java module. It makes the packages very well encapsulated.

3. Detection of missing classes at startup

From Java 9 and onward, Java applications are now also packaged in Java modules. Therefore, every application module has to specify what Java API modules it requires.

To make sure no modules are missing, JVM now checks the complete module dependency graph at startup. If any required modules are not found, the JVM reports the missing Java modules and shuts down.

Before Java 9, it was not possible to detect missing classes until the application itself tries to use it at runtime. By that time, the application would crash if the required class is not found.

Java modules: The basics

After discussing what Java modules are and their benefits, let’s take a look into some of the basics of modules in Java.

1. Number of packages

Java modules often contain one or more Java packages that belong to the same application. A module could be a complete Java application, a Java Platform API, or it can be a third-party API.

2.  Java modules naming

A Java module must have a unique name. It follows the same naming conventions as Java packages but it should not contain underscores, Java wants to use underscore as a reserved identifier in the future so avoid using them even in packages and classes.

For example, here is a valid module name

com.shaharyar.module01

3. Module descriptor

Modules in Java require a Java module descriptor named module-info.java. It must be located in the module root directory. The module descriptor specifies which packages are needed to be exported, and what other packages the module requires.

An empty Java module descriptor would look like this:

module com.shaharyar.module01 {…}

First comes the module keyword, followed by the name of the module, lastly a set of curly brackets in which the exported packages and required modules will be specified.

4. Module exports

As mentioned before, packages that are required by the other modules must be explicitly mentioned. The exported packages are declared in the module descriptor.

This is how an export declaration is written inside the module descriptor:

module com.shaharyar.module01 {
    exports com.shaharyar.module01;
}

The above code exports the package called com.shaharyar.module01.

Developers can also export a subpackage but it must also be declared explicitly in the module descriptor:

module com.shaharyar.module01 {
    exports com.shaharyar.module01;
    exports com.shaharyar.module01.util;
}

You can also independently export a subpackage without its parent package.

If we change the above example to just export the subpackage, it would be done like this:

module com.shaharyar.module01 {
    exports com.shaharyar.module01.util;
}

5. Module requires

Contrary to exporting, if a Java module is required by a module to do a task, the required Java module must be specified in the module descriptor similar to export modules:

module com.shaharyar.module01 {
    requires javafx.graphics;
}

Types of modules in Java 9

There are four types of modules in Java 9,

1. Platform modules

The set of Java 9 modules that contains parts of the modified modular structure JDK are called platform modules.

2. Application modules

These modules are what are made when developers build an application in modules. Different functionalities are added in form of modules in an application. All third-party dependencies are also part of this category.

3. Automatic modules

Those jar files that are placed at the module path without module descriptors are automatic modules. Several pre-existing libraries have yet to be modularized. They can be used in a modular application as automatic modules.

4. Unnamed modules

When a class or a JAR file is placed on the classpath, but not on the module path, it is automatically considered an unnamed module. Since it does not have any name, it can read and export all the modules. It is primarily used to maintain backward compatibility with previously written code.

Limitations in Java 9 modules

1. No circular dependencies

The module dependency graph must always be an acyclic graph which means that circular dependencies between modules are not allowed in Java 9. For instance, if module M1 requires module M2, then module M2 cannot require back module M1.

2. Split packages are not allowed

Having two modules export the same package is referred to as a split package. A split package means the total content of the package will be split between multiple modules. It can happen if multiple modules attempt to export the same package at the same time. It is restricted in Java 9 and if tried, JVM will complain at start-up.

How to compile a module in Java 9

To compile Java 9 modules, you need to use the javac command that comes in Java SDK. You must have the javac command from the JDK installation on your path for it to properly work.

This is how you can compile a module:

javac -d out --module-source-path src/main/java --module com.shaharyar.module01

you can also replace the javac code above with the full path where the javac command is located, like this:

"C:\Program Files\Java\jdk-9.0.4\bin\javac" -d out --module-source-path 
src/main/java --module com.shaharyar.module01

Here, javac is used to compile the module. It writes the compiled result into the location specified after the -d argument. The –module-source-path points to the source root directory, (not module root directory). The source root directory is normally one level up from the module root directory.

Lastly, The –module argument specifies which Java module is to be compiled. In the example above, it is the module com.shaharyar.module01. You can also use the same command to specify more than one module to be compiled by writing their names, separated by a comma. See this example:

... --module com.shaharyar.module01, com.shaharyar.module02

How to run a module in Java 9

Now we are all ready to run the main class of a Java module.

To do that, you have to use the java command, like this:

java --module-path out --module com.shaharyar.module01/
com.shaharyar.module01.Main

similar to compiling the module, the –module-path argument points to the root directory where all the compiled modules are present.

The –module argument specifies which module and main class to run. In the above code snippet, the module name is com.shaharyar.module01 and the main class name is com.shaharyar.module01.Main. They both are separated by a slash (/).

Conclusion

The modules in Java 9 are a sophisticated addition. If you are interested in learning more about the Java 9 modules, check out some of our other blogs!

See Also: Modularization in Java: What Is It?

Author

Shaharyar Lalani is a developer with a strong interest in business analysis, project management, and UX design. He writes and teaches extensively on themes current in the world of web and app development, especially in Java technology.

Write A Comment