Classes are the basic unit of a program in Java. Packages are used to manage classes and modules are used to manage packages.
Modules were introduced in Java 9. Before that, an application consists of packages that hold classes. It is a problem in large codebases. A public class means that anyone from anywhere could access that class, which can lead to unwanted dependencies. Modules are uniquely named, reusable groups of related packages as well as resources.
A Module controls which packages should be private for internal use only and which should be public for other modules to use. In modular Java, a public class no longer means that anyone can access that class from anywhere, instead, it is public within a module only, unless module exports its package for other modules to use.
From Java 9, the language itself has broken down into modules. Run java --list-modules
on JDK 9 or above. It will print out a list of Java modules.
$ java --list-modules
java.base@11.0.5
java.compiler@11.0.5
java.datatransfer@11.0.5
java.desktop@11.0.5
java.instrument@11.0.5
.
.
.
You can check any module's meta-data with the command: java --describe-module [module name]
. For example:
$ java --describe-module java.logging
java.logging@11.0.5
exports java.util.logging
requires java.base mandated
provides jdk.internal.logger.DefaultLoggerFinder with sun.util.logging.internal.LoggingProviderImpl
contains sun.net.www.protocol.http.logging
contains sun.util.logging.internal
contains sun.util.logging.resources
exports java.util.logging
the classes in this package are accessible to other modules.
requires java.base mandated
this module depends on another module named: mandated.
provides ...
this module is providing a service implementation (we won't cover services in this article)
contains
this is an internal package, accessible within module only.
A bare minimum Java module Example
Our sample application will contain two modules, one for utilities called utils and one main application module that will use the utils module. Let's code it up:
Create a directory JavaModuleExample
and cd
into it:
$ mkdir JavaModuleExample
$ cd JavaModuleExample/
Create root and subdirectories to contain code. Utils module will be in module.utils
directory and App module will be in module.app
directory. Both directories will contain their sub-packages. Let's create them:
$ mkdir -p module.utils/com/module/utils
$ mkdir -p module.app/com/module/app
Final Directory Structure would look like:
$ tree
.
├── module.app
│ └── com
│ └── module
│ └── app
└── module.utils
└── com
└── module
└── utils
8 directories, 0 files
In above structure, module.app
has package com.module.app
and module.utils
has package com.module.utils
.
Utils Module
Let's complete module.utils
. Create a new Java File Utils.java
in package com.module.utils
with following cat
command. It will start waiting for text input.
$ cat > module.utils/com/module/utils/Utils.java
paste following code in console, press Ctrl+D
when finished
package com.module.utils;
public class Utils {
public static int sum (int arg0, int arg1) {
return arg0 + arg1;
}
}
[Press Ctrl+D]
To tell Java we are writing a module, we need to provide module-info.java
at the root level of the module. Create the following file again with cat
command:
$ cat > module.utils/module-info.java
paste following code in console, press Ctrl+D
when finished
module module.utils {
exports com.module.utils;
}
[Press Ctrl+D]
In the above file, we are specifying our module, the name of the module is module.utils
, you can name it whatever you want but is a convention to name module the same way as we name packages.
The Other thing is we are exporting a package com.module.utils
. We want this package to be available in other modules. If you don't explicitly export it, then by default, it will be only accessible within the module itself.
That's it, we have created a simple module.
App Module
The Next step is to complete module.app
. Again, we need module-info.java
at the root of our App module and since our app module has a dependency on the utils module, we need to specify that dependency in module-info.java
. Create module-info.java
with the following command:
$ cat > module.app/module-info.java
paste following code in console, press Ctrl+D
when finished
module module.app {
requires module.utils;
}
[Press Ctrl+D]
In the above file, we need to explicitly tell which modules do we need as a dependency. requires module.utils
is specifying we need utils module in our app module.
Now Create Main
class to use Utils
.
$ cat > module.app/com/module/app/Main.java
paste following code in console, press Ctrl+D
when finished
package com.module.app;
import com.module.utils.Utils;
public class Main {
public static void main(String[] args) {
System.out.println(Utils.sum(1,2));
}
}
[Press Ctrl+D]
we are calling sum(...)
function from Utils
class which exists in the util module.
Finally, our application would look like:
$ tree
.
├── module.app
│ ├── com
│ │ └── module
│ │ └── app
│ │ └── Main.java
│ └── module-info.java
└── module.utils
├── com
│ └── module
│ └── utils
│ └── Utils.java
└── module-info.java
8 directories, 4 files
Compile
Run following command to compile code:
$ javac -d outDir --module-source-path . $(find . -name "*.java")
javac
is java compiler that will compile java code to byte code
-d outDir
is where our compiled code will go
--module-source-path .
we are specifying module source path, which is current directory .
$(find . -name "*.java")
we are specifying which files to compile (all files ending with .java)
Run
Run following command to run code:
$ java --module-path outDir -m module.app/com.module.app.Main
3
java --module-path outDir
will specify compiled modules directory
-m module.app/com.module.app.Main
specifying which class to run, Main
class in module.app
3
is printed as a result, which is the result of Utils.sum(1,2)
, the code we have written in our Main class in the App module.
That was a basic introduction to modules in Java. As a side note, I would like to mention that you should not confuse Java modules with maven modules or IntelliJ IDEA modules. Maven and IntelliJ IDEA have their concepts of modules too. Also, IntelliJ IDEA supports Java modules too see their blog post here.
Originally Published at https://thebackendguy.com/java-modules-introduction/
Top comments (0)