A Java module is a self-contained unit of code that groups related packages, resources, and configuration.
Introduced in Java 9, modules improve encapsulation, performance, and maintainability.
module com.example.myapp {
requires com.example.utils;
exports com.example.myapp.api;
}| Keyword | Description |
|---|---|
module |
Declares a module |
requires |
Declares a dependency on another module |
exports |
Makes a package accessible to other modules |
opens |
Allows runtime reflection access (e.g., by frameworks like Jackson) |
uses |
Declares a service interface this module will consume |
provides ... with |
Declares an implementation of a service interface |
requires transitive |
Re-exports a dependency to downstream modules |
requires static |
Marks a compile-time-only dependency (not needed at runtime) |
exports ... to |
Makes a package accessible to specific modules only |
my-module/
βββ src/
β βββ main/
β βββ java/
β βββ module-info.java
β βββ com/mycompany/mypackage/
β βββ MyClass.java
| Feature | exports |
opens |
|---|---|---|
| Compile-time use | β Required | β Not accessible |
| Reflection support | β Not allowed | β Accessible via reflection |
| Use case | Public APIs | JSON mapping, ORM, frameworks, etc. |
// module: payment.api
package com.mycompany.payment;
public interface PaymentGateway {
void pay(String customer, double amount);
}// module: payment.impl
module payment.impl {
requires payment.api;
provides com.mycompany.payment.PaymentGateway
with com.mycompany.payment.impl.StripePaymentGateway;
}// module: checkout
ServiceLoader<PaymentGateway> loader = ServiceLoader.load(PaymentGateway.class);
loader.findFirst().ifPresent(gw -> gw.pay("Zied", 100));- β Start modularizing early in new projects
- β Keep one responsibility per module
- β Export only what you intend to expose
- β
Use
opensonly for framework-based reflection - β
Use
provides/usesfor pluggable architecture - β Test each module independently
- β Forgetting to export a package needed by other modules
- β Attempting reflection on closed packages (without
opens) - β Cyclic dependencies between modules
- β Mixing modules with legacy classpath without control
javac -d out --module-source-path src $(find . -name "*.java")java --module-path out -m my.module/com.mycompany.Main