Java Platform Module System (JPMS)¶
Status: 🟢 Active | Owner: Java Guild
Policy¶
JPMS (module-info.java) is optional for application services and recommended for shared libraries.
- New shared libraries: Adopt JPMS to enforce encapsulation of internal packages.
- Application services (Spring Boot): JPMS adoption is optional; many Spring Boot internals are not fully JPMS-compatible. Evaluate before adopting.
- Existing codebases: Do not retrofit JPMS without a specific justification.
When to Use JPMS¶
Use JPMS when you want to:
- Prevent consumers of a library from accessing internal implementation packages.
- Explicitly declare dependencies on other modules.
- Produce a smaller JRE via
jlinkfor CLI tools.
module-info.java for a Library¶
// module-info.java at src/main/java/
module com.acme.shared.auth {
// Exported API packages
exports com.acme.shared.auth.api;
// Internal packages — NOT exported
// com.acme.shared.auth.internal is invisible to module consumers
// Required modules
requires java.net.http;
requires com.fasterxml.jackson.databind;
// Open for reflection (e.g. for Jackson serialisation)
opens com.acme.shared.auth.api to com.fasterxml.jackson.databind;
}
Spring Boot Compatibility¶
Spring Boot's annotation processing (@SpringBootApplication, @Component scanning) relies heavily on reflection. If you adopt JPMS in a Spring Boot app, you must open your packages to Spring:
module com.acme.order.service {
requires spring.context;
requires spring.web;
opens com.acme.order.service to spring.core;
opens com.acme.order.service.web to spring.web;
}
This is verbose and error-prone. This is why JPMS is not recommended for Spring Boot application services.
Unnamed Module Fallback¶
Libraries without a module-info.java are placed on the classpath as part of the unnamed module, which automatically reads all named modules and is readable by all named modules. This maintains backward compatibility.
References¶
Last reviewed: 2025-Q4 | Owner: Java Guild