Java Modules

A module is a named set of packages, resources and native libraries. Its a new Java entity that is similiar to an executable jar in its production state, but includes a name and a descriptor class that provides benefits that did not exist prior to Java 9.

The benefits of using modules are:

The smaller sets of code nicely packaged into modular jar files comprise the Modular JDK

The modular JDK kit is split into two sections SE and JDK

Describe the Modular JDK

Before Java 9 the JDK was a monolithic set of packages, packaged in one file (rt.jar), which any Java application would need to deploy along with its own code. Even if your application only ever used one class in a package, you still needed the rt.jar file which included the neccessary frameworks. Project Jigsaw was the name of the project to modularize the JDK.

The goals of project Jigsaw are:

A module graph is a diagram which attempts to visualize the module dependencies of a particular module, it only includes dependencies and not packages.

The java.base module is described as the foundational API of the Java SE Platform, which includes the core packages (java.lang, java.util, java.io, etc)

Commandline tools to view Java modules
java --list-modules                             # view SE and JDK modules
java --describe-module java.logging             # get more details of a module (version, state, etc)
jdeps --print-module-deps -m java.sql           # view summary of dependencies of a specific module
jdeps --list-reduced-deps --module java.sql     # same as above but different formatting

Declare modules and enable access between modules

Below is a simple module using intellij IDEA, the first screenshot is a normal Java not using modules

If you notice that when intellij runs the code you can see that it still uses the classpath parameter

By simply adding a module-info.java file in the src root folder and then rerunning the code you can see that now is uses the -p (path) and -m (module) parameters and thus is running as a module, there are a number of commandline tools that you can use to create jars, run Jars list dependencies, etc

Execute the module
java -p out\production\ -m MyFirstModule/modular.HelloModularWorld
java --module-path . --module MyFirstModule
java -p . -m MyFirstModule                                         # shorthand of above

Note: there are a number of different parameters that you can use to execute the module
Create a Jar file
jar --create --file MyFirstModule.jar --main-class modular.HelloModularWorld -C out\production\MyFirstModule\ .
          
Note: the dot at the end means all files
List contents of a jar file
jar -f MyFirstModule.jar --list
List dependencies
jar -f MyFirstModule.jar -d
java [--module-path|-p] . [--describe-module|-d] MyFirstModule

Note: shortcut parameters can be used for example -p is the same as --module-path
List class dependencies
jdeps MyFirstModule.jar                     
jdeps [-v|-s] --module-path .;out MyFirstModule                 # -v verbose and -s summary (good for module graph)
jdeps --module-path .;out -m MyFirstModule
jdeps --module-path .;out --check MyFirstModule

Note: -p is not the same as --module-path in other commands, -p is package when using jdeps
List all modules that the code uses
java --list-modules -p MyFirstModule
Dry run checking module dependencies are satisfied
java --dry-run -p . -m MyFirstModule
java --dry-run -p .;out -m MyFirstModule                         # if using multiple modules you can also add other directories as well

Note: The code does not execute but checks all the dependencies
Compiling modules
javac -d out\production --module-source-path . -m MyFirstModule

Describe how a modular project is compiled and run

The module-info.java file has a number of directives that can be used within the file as shown in the table below, I will only cover the basics whicxh is part of the OCA exam which are requires and exports

Module directive Example Description
requires
requires org.modules.a;
requires java.logging;
requires transitive org.modules.d;
requires static org.module.e;
A module specified in the requires directive is one which exports packages that the current module may or does have a dependency on. The current module is said to read the module specified in the required directive.

A requires directive with the transitive modifier allows any module which requires the current module to have an implicit requires directive on the specified module.

A static directive requires the specified module at compile time but its optional at run time.
exports
exports org.pkg.base;
exports org.pkg.util to org.module.a, org.module.b
A package specified in the exports directive will expose its public and protected types, to modules that read the current module.

The 'to' keyword make an exports directive qualified and will be followed by a comma delimited list of modules that are termed friends of the current module. Friends of a module have access to public and protected types of the exported package. No other modules will have access. You limit the exposure of the exported package types to its friends.

So creating a 2 module example you can see below that one modules exports its package and the other requires a module, notice that we export the package and require the module