Java Module System — Part 1

Well at-least the public classes that are meant to be internal to the library.

Traditionally library developers used to create the package with the name internal as the unwritten law for types not to be used by clients of the library but there was no enforcement of this.

Another problem is that as the JVM sees the package name as just names, we could have two jars with same package name and hence compromise the application integrity.

It could be that the classes that are required for the application to run is missed all together and the run-time throws a NoClassDefFoundError when execution point hits the point where the class is called for.

Jar Hell like Dll hell is a real issue where in large codebases with a lot of dependencies and the developer has to be extremely careful of what is being extended or called.

The codebase of our dear JDK is itself 20 years old and because of backward compatibility there is a large amount of the codebase that is pulled in even for a tiny application.

This size also has a hit on the performance of the JVM.

Even classes for outdated technology like CORBA is pulled into the runtime of your modern distributed, functional, highly-concurrent wonder code.

Writing Modular CodeAt its simplest modular code in java involves:Its nameThe packages a module exposesThe dependencies of a moduleThere are other nuances to consider but this is where a novice would begin to design his library as modules.

Maven projects (and most other build tools) use modules already to segregate a large codebase into smaller units.

This is however only at the codebase level and all the dependencies are still handled by classpaths.

With JPMS classpaths become less relevant as the module based jvm parameters like “ — module-path” , “ — module”, etc.

have much more control than the traditional classpathIn the above project I have defined four modules for my applicationcom.

jtk.

nutrition.

cli: Module consisting of the main method to run the application in command linecom.

jtk.

nutrition.

ui: Module having the UI component for application (and hence has dependency on the javafx modules)com.

jtk.

nutrition.

loader: Module for loading the data for the main programcom.

jtk.

nutrition.

sort: Module consisting of various sorting algorithm for the data being loadedAs you can see the dependency is defined such that the cli and ui components depend on the loader and sorting modules; the ui additionally depends on the javafx modules for the front end.

When using maven they are defined as modules, this is as per normal project setup and has nothing to do with JPMS.

What makes it different though is the special module-info.

java file specified in each of those module source folder as shown below.

These files configure the modules for various behaviournutrition-loader/src/main/java/module-info.

javamodule com.

jtk.

nutrition.

loader{ requires java.

logging; exports com.

jtk.

nutrition.

loader.

model; exports com.

jtk.

nutrition.

loader.

util; }nutrition-sort/src/main/java/module-info.

javamodule com.

jtk.

nutrition.

sort{ exports com.

jtk.

nutrition.

sort.

util;}The requires keyword indicates the module requires this module as dependency as it might be calling classes from that module.

The exports keyword indicates that this module only exposes those packages with in the modules to the other modules.

This means that if there was a package com.

jtk.

nutrition.

loader.

internal, the classes even though public cannot be called from other modules.

This effectively encapsulates the internal code from the client application which previously wasn’t possible.

nutrition-ui/src/main/java/module-info.

javamodule com.

jtk.

nutrition.

ui { exports com.

jtk.

nutrition.

ui; requires java.

logging; requires javafx.

controls; requires javafx.

base; requires javafx.

graphics; requires com.

jtk.

nutrition.

loader; requires com.

jtk.

nutrition.

sort; }Here the requires keyword makes a dependency to the nutrition-loader and nutrition-sort modules defined above.

But it can only access those packages that the module has exposed, i.

e.

com.

jtk.

nutrition.

loader.

model, com.

jtk.

nutrition.

loader.

util and com.

jtk.

nutrition.

sort.

util.

Once the modules are designed we should be able to build by runningmvn clean packageYou could also build the application using command line by running the following for each modulejavac -d target/classes -p $PATH_TO_FX –module-source-path src $(find .

-name ‘*.

java’)— -module-source-path: Tells the compiler where the source files for the modules are.

–module-path (-p): Tells the compiler/runtime where the compiled modules are that need to be considered for compiling/running code your codeBut I found this too tedious and depend on maven to do the hard work.

And then run using the below command from the project folder (windows)java -p nutrition-loader arget.utrition-loader-1.

0-SNAPSHOT.

jar;nutrition-ui arget.utrition-ui-1.

0-SNAPSHOT.

jar;C:UsersjubinappsJavajavafx-sdk-11.

0.

2lib -m com.

jtk.

nutrition.

ui/com.

jtk.

nutrition.

ui.

MainAs you can see the run-time is completely devoid of the class-path references and in its place uses the module based VM parameters-p ( —-module-path ) to indicate the jars/classes where the modules are build to; in my case the target folder for the project-m (–module) to indicate the main class that needs to run and its associated module: com.

jtk.

nutrition.

ui/com.

jtk.

nutrition.

ui.

MainObservable modules: These are the set of modules that a particular module depends on either by configuration or by default.

Usually, the below command should be displaying the entire set of observable modules but however it doesn’t seem to work for maven projects.

java –list-modules –module-path target/classesAs an alternative I right-click on intellij project to generate module diagram, which gives me a visual view of the module dependencies (first diagram above).

Additionally, I had to add the following dependency in my pom.

xml for the ui module to work.

<dependency> <groupId>org.

openjfx</groupId> <artifactId>javafx-controls</artifactId></dependency><dependency> <groupId>org.

openjfx</groupId> <artifactId>javafx-fxml</artifactId></dependency>Summary:Essentially we solved two problems so far with the module system.

We are able to selectively decide what packages are to be exported from a module there by effectively encapsulating the implementation (i.

e.

even public classes in the jars are not accessible) and configuring the modules such that each module knows exactly what it depends on without having all the jars in the class-path and hoping for the best.

I will add a reference to the code base once I have pushed it to github.

.

. More details

Leave a Reply