skip to content

In a modern Java codebase, how do sealed JARs, JAR signing, and JPMS strong encapsulation relate — which would you reach for and why?

level: principalimportance: nice to knowfreq 14%

answer

  1. sealing = cohesion (one jar), signing = provenance, JPMS = access control
  2. JPMS strictly stronger than sealing for encapsulation
  3. signing is orthogonal to both — always relevant for supply chain
  4. modules forbid split packages (subsumes sealing's anti-split)
  5. legacy classpath → sealing as cheap defense-in-depth

basics

~20 s

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

These 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

for a junior

Can state that the three features exist and that they address different goals (one-jar packages, who-published-it, hiding internals).

for a middle

Distinguishes sealing vs signing clearly and knows JPMS modules provide stronger encapsulation than sealing.

for a senior

Explains the distinct axes, why JPMS subsumes sealing's encapsulation role, and that signing is orthogonal supply-chain integrity.

for a principal

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.

context