Java Module System (JPMS)
Fast recall
Quick revision
Core answer
Whether you know the problem JPMS solves, how module-info.java works, and how it interacts with reflection.
Thinking modules are the same as Maven/Gradle modules — JPMS is a JVM-level feature, independent of build tools.
Discuss automatic modules (unnamed module), --add-opens for libraries, and how GraalVM uses module boundaries for native image dead code elimination.
Interview-ready guide
Interview answer
The Java Platform Module System (JPMS), introduced in Java 9, adds a formal module layer above JARs. Each module explicitly declares what packages it exports and what other modules it requires — and the JVM enforces these access rules at runtime, preventing the "any class can access any class" free-for-all of the classpath era.
What JPMS adds:
- Each module declares
exports(what it exposes) andrequires(what it depends on) inmodule-info.java - Packages not exported are invisible to other modules — enforced by the JVM at runtime with
IllegalAccessError - Even reflection is blocked unless you add an
opensdirective
JPMS vs Maven modules:
- Maven modules: organize source code for the build tool — no runtime enforcement
- JPMS modules: JVM-enforced access boundaries — runtime validates every access
- Why Spring Boot launch scripts include
--add-opensflags: Spring needs reflection access to packages JPMS doesn't export by default
Migration approach:
- Start with
Automatic-Module-Namein your JAR manifest to stabilize the module name - Add
module-info.javaonce internal packages are clean and stable
Practical payoffs:
- Large codebases: prevents accidental cross-module dependencies that create maintenance nightmares
- GraalVM native images: module boundaries enable aggressive dead-code elimination at build time
I recommend JPMS at scale — for smaller projects, the migration cost often exceeds the benefit unless you're targeting GraalVM native image.
Java Module System (JPMS)
Direct Answer
JPMS (introduced in Java 9) solves the classpath hell problem — any code could access any public class. Modules declare what they export (publicly accessible packages) and what they require (dependencies), enforcing strong encapsulation at the JVM level. A module is defined in module-info.java at the source root.
Deep Dive & Architecture
Attack GC pause times in this order, by impact: (1) reduce allocation rate in application code (eliminate autoboxing, reuse buffers, use primitive collections, stream more), (2) choose the right GC algorithm for your latency target (G1 for general use, ZGC or Shenandoah for sub-millisecond pauses), (3) size the heap correctly — too small causes frequent GC, too large causes longer pauses for non-concurrent collectors, (4) tune the chosen collector with appropriate flags (-XX:MaxGCPauseMillis, -XX:G1ReservePercent, -XX:G1HeapRegionSize).
Always measure with GC logs first; never tune flags blindly.
JPMS (introduced in Java 9) solves the classpath hell problem — any code could access any public class. Modules declare what they export (publicly accessible packages) and what they require (dependencies), enforcing strong encapsulation at the JVM level. A module is defined in module-info.java at the source root.
Restarting first and analyzing later (you may lose the heap dump if it wasn't on a persistent volume); or jumping to fixes before identifying which OOM subtype occurred
Common Mistakes & Pitfalls
Thinking modules are the same as Maven/Gradle modules — JPMS is a JVM-level feature, independent of build tools.
Check your understanding
Answer these without looking back at the article.
- How does Java reflection work, and what are the performance costs you must account for?
- Compare Java NIO with traditional IO — when would you choose one over the other?
- How does Java annotation processing work at compile time vs runtime, and what are the use cases?
Related interview prep categories
2Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.