In a modern Java codebase, how do sealed JARs, JAR signing, and JPMS strong encapsulation relate — which would you reach for and why?
answer
- sealing = cohesion (one jar), signing = provenance, JPMS = access control
- JPMS strictly stronger than sealing for encapsulation
- signing is orthogonal to both — always relevant for supply chain
- modules forbid split packages (subsumes sealing's anti-split)
- legacy classpath → sealing as cheap defense-in-depth
basics
~20 sThey solve different problems: sealing keeps a package's classes in one JAR, signing proves who published a JAR and that it's unchanged, and JPMS modules strongly hide non-exported packages. Use modules for encapsulation, signing for provenance, sealing only for legacy classpath cases.
solid answer
~50 sThese three are often lumped under 'JAR security' but address different axes. Sealing is a classpath-era integrity feature: it stops other JARs from injecting classes into your package and gaining package-private access, but it's enforced only at class-load time and is weak compared to modern options. JAR signing is about provenance and tamper-detection — it tells you who published the artifact and that bytes are unchanged; orthogonal to sealing and still very relevant for supply-chain trust. JPMS strong encapsulation (Java 9+) is the modern answer to the encapsulation problem sealing partially addressed: a module's non-exported packages are simply invisible and inaccessible from outside, enforced by the module system, with no other JAR able to claim or read them. So in a modular codebase I'd rely on JPMS for encapsulation, keep signing for distribution integrity, and treat sealing as a lightweight option mainly for non-modular/legacy classpath deployments.
go deeper
Can state that the three features exist and that they address different goals (one-jar packages, who-published-it, hiding internals).
Distinguishes sealing vs signing clearly and knows JPMS modules provide stronger encapsulation than sealing.
Explains the distinct axes, why JPMS subsumes sealing's encapsulation role, and that signing is orthogonal supply-chain integrity.
Frames a coherent strategy — modules for encapsulation, signing for provenance, sealing for legacy hardening — and reasons about combining them (signed jlink images) and trade-offs across a real distribution pipeline.
## Three different questions It helps to separate the questions each mechanism answers: - **Sealing** — *“Are all classes of this package from one JAR?”* (cohesion / anti-injection) - **JAR signing** — *“Who published this JAR and is it unaltered?”* (provenance / integrity) - **JPMS strong encapsulation** — *“Who is even allowed to see and use this package?”* (access control / encapsulation) They are independent: you can sign a sealed modular JAR, or do none of the above. ## Sealing, recapped Declared by `Sealed: true` in `META-INF/MANIFEST.MF` (whole JAR or per package). It forces every class of a sealed package to load from the same JAR, throwing a `SecurityException` otherwise. Its security value is preventing a rogue JAR from adding a class to your package — which would otherwise gain **package-private** access to your internals or shadow a class. Limits: it's a classpath construct, checked at **load time**, and does nothing about *who* may *call* exported API — anything public is still fully accessible. It also predates and is largely subsumed by modules for the encapsulation use case. ## Signing, recapped Uses `keytool` + `jarsigner` to attach a per-entry digest chain (`MANIFEST.MF` → `.SF` → `.RSA/.EC` block with the certificate). Gives **integrity** and **authenticity**, not confidentiality. It is the relevant tool for **supply-chain trust**: verifying a dependency truly came from its maintainer and wasn't swapped. It says nothing about visibility or cohesion — a different axis entirely from sealing/JPMS. ## JPMS strong encapsulation The **Java Platform Module System** (Project Jigsaw, Java 9) introduces a `module-info.java` per module declaring `exports` (which packages are visible) and `requires` (dependencies). A package **not exported** is invisible to other modules: code outside cannot import, reflect into (without `opens`), or extend it — enforced by the module layer at the boundary, not merely by a load-time origin check. This is **strictly stronger** than sealing for encapsulation: - Sealing only stops *adding* classes to your package; JPMS stops *outsiders accessing* your package at all. - Sealing is per-archive; modules are first-class units with explicit, verified dependency graphs. - Modules also enable reliable configuration (no split packages — a package can't span modules, which actually subsumes sealing's anti-split goal) and a smaller attack surface via `jlink` custom runtimes. ## A decision rubric - **Need to hide internals / enforce a public API?** Use **JPMS modules** (or, lighter, package-private + good API design). Sealing is a weak substitute. - **Need to prove provenance / detect tampering of distributed artifacts?** Use **signing** — independent of the above; do it regardless of encapsulation choice. - **Stuck on the classpath (non-modular app, old libraries)?** **Sealing** is a cheap hardening that prevents package injection — reasonable defense-in-depth where modules aren't feasible. - **High-assurance distribution?** Combine: a **modular, signed** runtime (e.g. `jlink` image of signed modules) gives encapsulation + provenance together. ## Common misframings to avoid - Treating sealing as encryption or as proof of publisher — it is neither. - Believing JPMS replaces signing — they're orthogonal (visibility vs. provenance). - Assuming sealing gives module-grade encapsulation — it only blocks class injection, not external access to public API. ## Bottom line In a modern codebase, reach for **JPMS** for encapsulation and split-package prevention, **signing** for supply-chain integrity, and keep **sealing** as a legacy-classpath hardening tool. They compose, but each owns a distinct axis.
- Does adopting JPMS make JAR signing unnecessary?No — they answer different questions. JPMS controls visibility and access between modules (encapsulation); signing proves who published an artifact and that it wasn't tampered with (provenance/integrity). You still sign modular JARs or jlink images for supply-chain trust, regardless of how strongly they encapsulate.
- Why is JPMS considered stronger than sealing for encapsulation?Sealing only prevents other JARs from adding classes to your package (a load-time origin check) but leaves all public API fully accessible. JPMS makes a non-exported package entirely invisible — outsiders cannot import, reflect into, or extend it — enforced by the module system, and it forbids split packages outright, which subsumes sealing's anti-split intent.
saying these in an interview costs you the question
- Saying JPMS replaces signing — they are orthogonal (access vs. provenance).
- Claiming sealing provides the same encapsulation strength as modules.
- Recommending sealing as the primary encapsulation mechanism in a modular codebase.
- Forgetting that signing should be applied regardless of the encapsulation approach.