What is a module in the Java Platform Module System (JPMS), and how do you declare one?
answer
- Module = named packages + descriptor
- module-info.java at the source root
- Compiles to module-info.class inside the JAR
- requires = dependency, exports = expose package
- Layer above packages (class → package → module)
basics
~20 sA module is a named group of related Java packages and resources. You declare it in a special file, module-info.java, at the root of your source code; it names the module and lists what it needs and what it shares.
solid answer
~40 sA module (introduced in Java 9) is a self-describing, named unit that bundles a set of packages plus their resources, together with a declaration of which other modules it depends on and which of its own packages it makes available. You declare it in module-info.java at the source root. A minimal form is just `module com.example.app { }`. Inside the braces go directives: `requires` for dependencies and `exports` to expose a package's public API. The compiler turns module-info.java into module-info.class, which ships inside the JAR (a 'modular JAR'). At compile and run time the module system reads these descriptors to build a reliable module graph. Modules sit one level above packages: a package groups classes, a module groups packages and adds explicit dependency and visibility rules.
code
java · 5 lines// File: src/module-info.java (at the source root)
module com.example.app {
requires java.logging; // depend on the java.logging module
exports com.example.app.api; // expose this package to other modules
}go deeper
Can state that a module is a named group of packages declared in module-info.java, and name the requires/exports directives.
Explains the source-root placement, the module-info.class compilation step, the modular-JAR concept, and distinguishes module name from package names.
Connects modules to the two goals (reliable configuration, strong encapsulation), explains classpath vs modulepath and automatic modules, and reasons about migration.
Frames JPMS in terms of large-codebase architecture: enforcing module boundaries, designing public API surface via exports, and trade-offs of adopting modules across many teams/artifacts.
## The problem modules solve Before Java 9, the unit of deployment was the **JAR** (a zip of `.class` files). JARs had no notion of identity or dependencies: you put them on the **classpath**, a flat list the JVM scanned top to bottom. Nothing recorded that `myapp.jar` needed `commons-lang.jar`; a missing dependency surfaced only at runtime as a `NoClassDefFoundError`. Also, `public` meant 'visible to everything on the classpath' — there was no way to keep a package internal to a JAR. **JPMS** (the Java Platform Module System, delivered in Java 9 under Project Jigsaw) adds a layer above packages to fix both problems. ## What a module is A **module** is a named collection of **packages** (a package is a namespace that groups classes, e.g. `java.util`) plus associated resources, *and* a **descriptor** that states: - the module's **name** (a unique identifier, e.g. `com.example.app`), - which other modules it **requires** (its dependencies), - which of its own packages it **exports** (makes accessible to other modules). Think of it as a JAR that finally carries a manifest of intent: 'I am called X, I need Y and Z, and I let others use these packages of mine.' ## How you declare one: module-info.java You create a single file named exactly **module-info.java** at the **source root** — the top of the directory tree that contains your packages (the same place the first package segment starts). Example layout: ``` src/ module-info.java <-- module descriptor com/example/app/Main.java com/example/app/util/Helper.java ``` A minimal descriptor: ```java module com.example.app { } ``` The braces hold **directives** (statements that configure the module). The two most common: - `requires some.module;` — 'I depend on `some.module`.' - `exports com.example.app;` — 'classes in package `com.example.app` are visible to other modules.' ## From source to bytecode: module-info.class When `javac` compiles your code, it compiles module-info.java into **module-info.class** — the binary form of the descriptor. That class file is placed at the root of the compiled output and packaged into the JAR. A JAR that contains a module-info.class is a **modular JAR**; the JVM reads the descriptor from it. So the descriptor is not a comment or a build-tool config: it is real, compiler-checked metadata baked into the artifact. ## Module name vs. package name The **module name** is a separate identifier from the package names it contains. A common convention is to name the module after its 'reverse-DNS' root package (e.g. module `com.example.app` exporting package `com.example.app`), but they are distinct concepts — one module can contain many packages. ## Where modules sit in the hierarchy Class → Package → **Module**. A class belongs to a package; packages are grouped into a module; modules are resolved together into a module graph. JPMS does not replace packages or classes — it adds the outermost layer that finally makes dependencies and visibility explicit and machine-checkable. ## Why it matters With a descriptor in hand, the toolchain can detect a missing dependency *before the program runs* and can stop code in one module from reaching into another module's non-exported internals. Those two guarantees are called **reliable configuration** and **strong encapsulation** — the headline goals of JPMS.
- Does every JAR have to be a module?No. A plain JAR with no module-info.class still works on the classpath. On the modulepath it becomes an 'automatic module' with a derived name and unrestricted exports. JPMS adoption is gradual; modules are opt-in.
- Can one module contain more than one package?Yes. A module typically groups several related packages. You export each package you want visible individually; packages you do not export stay internal to the module.
A plain JAR is a sealed box of parts with no label. A module is the same box with a shipping manifest taped on: its name, what it needs to function, and which parts it lets others take.
saying these in an interview costs you the question
- Saying a module is just a renamed JAR — the key difference is the compiler-checked descriptor with explicit dependencies and exports
- Confusing module name with package name (they are separate identifiers)
- Claiming module-info.java stays as source at runtime — it compiles to module-info.class
- Putting module-info.java in a package folder instead of the source root