Core Java

Java 9, Jigsaw, JPMS, and Modules: A Personal Exploration

Java 9 delayed so many times because of Project Jigsaw, and you may be heard a lot of thing about modules, modularity, and other stuff, so, what it’s all about? What the heck is modularization and what do we mean by modularized platform? Java Platform Module System (JPMS)? Is it going to be a revolution in Java ecosystem?
This post is my exploration of the most important thing that happened to the JDK, the Module System. I will explain what modularization is, why you need it, and how you can create your modularized project.
 
 
 

What & Why:

Maintainability is one of the most significant concerns in software design and evolution. We want a code base that is loosely coupled, highly cohesive, extremely readable and can be understandable in one eye shot. We design our classes and organize them in packages. So far so good, but when we have hundreds of packages the dependencies between them is not visible in one eye shot. Therefore, we need something more than packages to organize our code base and makes it more maintainable.
Another problem is java classpath and how it runs our codes. All jar classes and libraries are flattened into the classpath. When these jar files have multiple version of a class on the runtime, Java ClassLoader can load only one version of that class, in this way, there is ambiguity about how your program is going to work, and ambiguity is a bad thing. This issue is so frequent that it has its name called “JAR Hell.”

Another problem with classpath is that it doesn’t follow the “Fail First” principle. You may have missing classes that exist in the classpath, but it doesn’t exist in the production environment. Until the JavaClassDefError exception at runtime, you can’t be sure what is missing. Finally, The big issue with classpath is encapsulation. Every class on the classpath access to each other and this is an encapsulation violation. We want to hide our internal APIs, and that’s why we need another level of encapsulation (“Strong Encapsulation”) and control the access to our classes in our packages.

Modules are going to fix these issues. What is a module? A module has a name, it groups related code and is self-contained. A module describes explicitly what it needs from other modules and which part of him is visible to other modules. In this manner, dependencies between modules are crystal clear. We have Strong Encapsulation which means we can hide our internal APIs, and finally, we now follow the “Fail First” principle therefore when there is a missing module or confliction you will get an error.


Modularizing JDK allows JDK developers to manage the huge complexity of it. When you write a tiny and straightforward application that doesn’t use RMI, CORBA, JavaEE, and other stuff, why you need a full, huge, and heavy Java Runtime Environment? Isn’t that wiser to have your Runtime Image that only contains the modules you need? Now with a modularized platform, it’s possible.
This is how JDK now looks like. On the bottom, we have “java.base” module that every other module implicitly or explicitly depends on. As you can see, this dependency graph is a DAG which means no circular dependency allowed.

The picture below shows essentially what module is. Each module has a module descriptor called “module-info.java.”

In module-info.java file you describe the name of your module, what it requires to work and which packages are visible outside this module. For example, you can see what packages java.sql exports (make visible) and which modules it requires.

So in the simplest form, the module-info.java looks like the image below:

In the next section, I will show how you can work with these modules and create your modules.

How:

First of all, you need to download and install Java 9. You can find it here.

Java Version

$ java -version
java version "9"
Java(TM) SE Runtime Environment (build 9+181)
Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode

Let’s build a project in IntelliJ IDEA:

The picture below shows how to create a module:

After creating a module, you need to create a module-info.java file inside the src:

I’ve built a project that has two module: “com.mhrimaz.gui” and “com.mhrimaz.logic.” You can see the structure of the project in the image:

In com.mhrimaz.logic module I have two classes called “InternalGreeting” and “Greeting.”

InternalGreeting.java

package com.mhrimaz.logic.internals;
 
public class InternalGreeting {
    public static String sayHello(String name){
        return "Hello, This Greeting is internal dear "+ name;
    }
}

Greeting.java

package com.mhrimaz.logic;
 
public class Greeting {
    public static String sayHello(String name){
        return "Hello, " + name;
    }
}

The module-info.java of com.mhrimaz.logic, is the following:

module com.mhrimaz.logic {
    exports com.mhrimaz.logic;
}

This means the package com.mhrimaz.logic (it’s a package name not a module name don’t confuse) is visible outside this module but the package com.mhrimaz.logic.internals is not visible.

The MianApplication file is a simple JavaFX program:

package com.mhrimaz.gui;
 
import com.mhrimaz.logic.Greeting;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
 
public class MainApplication extends Application {
 
 
    @Override
    public void start(Stage primaryStage) throws Exception {
        Label label = new Label(Greeting.sayHello("Hossein"));
        StackPane pane = new StackPane();
        pane.getChildren().add(label);
 
        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

It seems that this package doesn’t need to export anything it only requires javafx.base and javafx.controls and in order to use Greeting class, we also should require com.mhrimaz.logic. The module-info of the com.mhrimaz.gui module looks like this:

module com.mhrimaz.gui {
    requires javafx.base;
    requires javafx.controls;
    requires com.mhrimaz.logic;
}

When we run our application we will get an exception:

Caused by: java.lang.IllegalAccessException: class com.sun.javafx.application.LauncherImpl 
(in module javafx.graphics) cannot access class com.mhrimaz.gui.MainApplication 
(in module com.mhrimaz.gui) because module com.mhrimaz.gui does not export com.mhrimaz.gui to module javafx.graphics

so obviously it tells that we need to export com.mhrimaz.gui package, This means javafx.graphics uses MainApplication to pass the Stage to it and you need to export your package to the javafx.graphics (Note: You can only export a package to specific module or export it to all modules)
So now the module-info.java looks like this:

module com.mhrimaz.gui {
    requires javafx.base;
    requires javafx.controls;
    requires com.mhrimaz.logic;
    exports com.mhrimaz.gui to javafx.graphics;
}

And the result seems like a bug in JavaFX implementation in Java 9 but this is our result:

The story doesn’t end here, There is a whole lot of details about modules, dependencies between them that you can read them in Java 9 Revealed or Java 9 Modularity book.

Reference: Java 9, Jigsaw, JPMS, and Modules: A Personal Exploration from our JCG partner Mohammad Hossein Rimaz at the Hossein Rimaz blog.

Mohammad Rimaz

Hossein currently is Software Engineering Student at K.N. Toosi University of Technology and a junior developer. He is a passionate Java programmer, especially interested in GUI programming with JavaFX. His interest includes Big Data, Data Visualization, and Recommender Systems
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button