What Are Modular Applications in Java?
A modular application in Java is an application structured using the Java Module System (JPMS), introduced in JDK 9. It allows developers to organize, encapsulate, and manage dependencies in a more scalable way compared to traditional classpath-based applications.
Why Were Modules Introduced?
Before Java 9, applications relied on the classpath to find classes. However, classpath-based applications had problems:
- Class Conflicts – If two JARs contained the same class, there was no built-in way to avoid conflicts.
- No Strong Encapsulation – Any public class in a JAR could be accessed, even if it wasn’t intended for external use.
- Large Monolithic JDK – Applications bundled unnecessary parts of the JDK.
- No Explicit Dependencies – The JVM had no knowledge of which libraries depended on which other libraries.
Java Modules Solve These Issues:
✅ Encapsulation – A module explicitly defines which packages it exposes.
✅ Explicit Dependencies – A module declares which modules it depends on.
✅ Smaller Deployments – Applications can use only the required parts of the JDK.
How Do Modules Work?
A module is a collection of packages with a special module-info.java
file that declares:
- What other modules it depends on.
- Which packages it exposes to other modules.
Example of a Simple Module
Let’s create a module named com.example.app
.
Step 1: Define a Module Descriptor (module-info.java
)
Inside the module folder, create a module-info.java
file:
module com.example.app {
requires com.example.utils; // Depends on another module
exports com.example.app; // Exposes this package to other modules
}
Step 2: Define a Package Inside the Module
Create a class inside the module:
📂 Project Structure
com.example.app/
│── module-info.java
└── com/example/app/Main.java
Main.java
package com.example.app;
public class Main {
public static void main(String[] args) {
System.out.println("Hello from a Java Module!");
}
}
Step 3: Compile and Run the Module
Compile
javac -d mods/com.example.app com/example/app/Main.java module-info.java
Run
java --module-path mods -m com.example.app/com.example.app.Main
Expected Output
Hello from a Java Module!
How Modules Differ from the Classpath
Feature | Classpath-Based Apps | Modular Apps |
---|---|---|
Encapsulation | No (all public classes accessible) | Yes (only exported packages are accessible) |
Dependency Management | Manual (JAR hell) | Automatic via requires |
Conflicting Classes | Possible conflicts | Prevented via module boundaries |
Security | Lower (all classes visible) | Higher (internal classes hidden) |
JDK Modules Example
The JDK itself is now modularized. Examples of built-in modules:
java.base
(always required, containsjava.lang
)java.sql
(for database operations)java.xml
(for XML processing)
Example:
module my.module {
requires java.sql; // Only load database-related APIs
}
When Should You Use Modules?
✅ Use Modules If:
- You are building a large-scale application.
- You want better dependency management.
- You need strong encapsulation.
❌ Don’t Use Modules If:
- You are maintaining old projects using classpath.
- You are using third-party libraries that are not modularized.
- You need a simple, small-scale application.
Key Takeaways
- Modular applications use the Java Module System (JPMS) instead of the classpath.
- Each module has a
module-info.java
file that declares dependencies and exports packages. - Encapsulation is enforced – non-exported packages cannot be accessed by other modules.
- The JDK itself is modularized, allowing applications to use only the required parts.
- Modules prevent “JAR Hell” by clearly defining dependencies.