How do you configure the application plugin for a JPMS (Java module) application, and what changes about mainClass and the launch?
answer
- mainModule + mainClass → module mode
- launches with --module-path and -m module/Class
- needs module-info.java; name must match
- classpath mode = unnamed module, no encapsulation
- start scripts honour mainModule too
basics
~10 sFor a modular app you also set application { mainModule = "com.example.app" } alongside mainClass. Gradle then launches with --module-path and -m instead of the classpath, running the named module's main class.
solid answer
~40 sIf your project has a `module-info.java`, you can run it as a true JPMS application by setting `mainModule` in addition to `mainClass`. `application { mainModule = "com.example.app"; mainClass = "com.example.app.App" }` tells the plugin to launch via the module path: it builds a `--module-path` from the runtime dependencies and invokes `java -m com.example.app/com.example.app.App` rather than putting everything on the flat classpath. This gives real module encapsulation at runtime. Dependencies that are proper modules go on the module path; the rest may land on the classpath depending on Gradle's module handling. The `run` task and the generated start scripts both honour `mainModule`. If you omit `mainModule`, even a project with module-info runs in classpath mode (the unnamed module), losing strong encapsulation.
code
kotlin · 5 linesapplication {
mainModule = "com.example.app" // from module-info.java
mainClass = "com.example.app.App"
}
// launches: java --module-path ... -m com.example.app/com.example.app.Appgo deeper
Awareness that there is a modular launch option is enough.
Know that mainModule plus mainClass triggers a --module-path launch.
Explain classpath vs module mode, encapsulation consequences, and automatic-module behaviour for legacy jars.
Weigh JPMS adoption trade-offs across an org's libraries and reflective frameworks before mandating module mode.
## Classpath mode vs module mode By default the application plugin launches in **classpath mode**: every runtime artifact is flattened onto `-cp`, and your code runs in the JVM's *unnamed module* — JPMS boundaries are not enforced even if a `module-info.java` exists. To launch in **module mode** (the Java Platform Module System), you tell the plugin the name of the application module: ```kotlin application { mainModule = "com.example.app" // the module name from module-info.java mainClass = "com.example.app.App" } ``` ## What changes at launch With `mainModule` set, the `run` task (a `JavaExec`) switches strategy: - It assembles a **`--module-path`** from the runtime dependencies instead of (only) a `-cp`. - It launches with **`-m <module>/<mainClass>`**, e.g. `java --module-path ... -m com.example.app/com.example.app.App`. This means the runtime respects `requires`, `exports`, and `opens` directives from `module-info.java` — reflective access and inter-module visibility are enforced, not best-effort. ## module-info and dependencies - Your own module must declare `module-info.java` with the matching module name. - Library dependencies are placed on the module path when they are explicit or automatic modules; Gradle's JVM module support decides path placement. Libraries without module metadata become *automatic modules* (named after the jar) on the module path. - The generated start scripts also use the module path, so a distributed modular app keeps the same launch semantics. ## Why it matters Strong encapsulation surfaces illegal access at runtime (`IllegalAccessError`) that classpath mode would silently allow. It also enables reliable configuration of services via `ServiceLoader` over the module path. The trade-off is stricter setup: every transitive dependency must be a real or automatic module, and reflective frameworks may need `opens`. ## Common gotcha Setting only `mainClass` on a project that *has* `module-info.java` does **not** opt you into module mode — you must also set `mainModule`. Forgetting it means you ship a 'modular-looking' build that actually runs unencapsulated.
- If a project has module-info.java but you only set mainClass, does it run in module mode?No. Without mainModule the plugin launches in classpath mode, running in the unnamed module, so JPMS encapsulation is not enforced even though module-info exists.
- What happens to a dependency jar that has no module-info?On the module path it becomes an automatic module, deriving its name from the jar (or its Automatic-Module-Name manifest entry). It can read other modules but exports all packages.
saying these in an interview costs you the question
- Claiming module-info.java alone switches the run to module mode.
- Saying mainModule replaces mainClass — you set both.
- Asserting all classpath dependencies are forbidden in module mode.