skip to content

What is a module in the Java Platform Module System (JPMS), and how do you declare one?

level: juniorimportance: should knowfreq 55%

answer

  1. Module = named packages + descriptor
  2. module-info.java at the source root
  3. Compiles to module-info.class inside the JAR
  4. requires = dependency, exports = expose package
  5. Layer above packages (class → package → module)

basics

~20 s

A 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 s

A 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
java
// 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

for a junior

Can state that a module is a named group of packages declared in module-info.java, and name the requires/exports directives.

for a middle

Explains the source-root placement, the module-info.class compilation step, the modular-JAR concept, and distinguishes module name from package names.

for a senior

Connects modules to the two goals (reliable configuration, strong encapsulation), explains classpath vs modulepath and automatic modules, and reasons about migration.

for a principal

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

context