skip to content

Sealed JARs & Code Signing

Sealed packages force every class of a package to come from one JAR, and jarsigner plus keytool attach a verifiable publisher identity. Interviewers use it when discussing supply-chain integrity for distributed artifacts.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What does it mean to seal a package in a JAR, and how do you configure it in the manifest?

level: middleimportance: should knowfreq 22%

answer

  1. Sealed: true in MANIFEST.MF
  2. all classes of a package from ONE jar
  3. main section seals whole jar; Name: pkg/ section seals one
  4. violation = SecurityException at class-load time
  5. Sealed: false carves out an exception

basics

~20 s

Sealing a package means every class in that package must come from the same JAR file. You turn it on by adding 'Sealed: true' to the JAR's MANIFEST.MF, for one package or the whole archive.

solid answer

~40 s

Sealing forces all classes of a Java package to be loaded from a single JAR. If code tries to load a class for a sealed package from a different JAR, the class loader throws a SecurityException at load time. You enable it in META-INF/MANIFEST.MF: to seal the whole archive, put 'Sealed: true' in the main section; to seal one package, add a per-entry section 'Name: com/example/foo/' followed by 'Sealed: true'. You can also un-seal a single package with 'Sealed: false' even when the whole JAR is sealed. The point is integrity: it stops someone from slipping mismatched or malicious classes into your package by putting them in another JAR on the classpath. It is purely a packaging/class-loading guarantee, separate from (though often paired with) JAR signing.

code

java · 15 lines
java
// META-INF/MANIFEST.MF (text content; not real Java, shown for layout)
//
// Manifest-Version: 1.0
// Sealed: true                 # seals the whole archive
//
// Name: com/example/open/      # ...but un-seal one package
// Sealed: false
//
// Name: com/example/secure/    # explicitly seal one package
// Sealed: true

// If another jar on the classpath tries to add a class to a sealed
// package, the class loader fails at load time:
//   java.lang.SecurityException: sealing violation:
//     package com.example.secure is sealed

go deeper

for a junior

Knows sealing means 'all classes of a package come from one JAR' and that it is switched on with 'Sealed: true' in the manifest.

for a middle

Can write both the whole-archive and per-package manifest entries, including 'Sealed: false' exceptions, and knows the violation is a runtime SecurityException.

for a senior

Explains the threat model (package-private access / class shadowing from a rogue JAR), where the check fires (class loader), and how it differs from and complements signing.

for a principal

Positions sealing against JPMS strong encapsulation, advises when each is appropriate in a packaging/dependency strategy, and reasons about its limits in modern modular builds.

## Background: JARs and packages A **JAR** (Java ARchive) is a ZIP file with a `.jar` extension that bundles compiled `.class` files plus a metadata file at `META-INF/MANIFEST.MF`. A **package** is a namespace grouping related classes, written dotted like `com.example.foo`, which maps to the directory `com/example/foo/` inside the archive. Normally the classes of one package can be spread across several JARs on the **classpath** (the list of locations the JVM searches for classes). `com.example.foo.A` might live in `app.jar` and `com.example.foo.B` in `plugin.jar`, and Java loads both without complaint. This is a flexibility, but also a risk: an attacker (or a careless dependency) could ship a JAR that adds its own class into *your* package and gain **package-private access** to your internals, or shadow/replace a class. ## What sealing does **Sealing** a package declares: *every* class in this package must be loaded from the *same* JAR. If, after a sealed package's first class is loaded from JAR X, the class loader is later asked to load another class of that package from a different source, it throws a `SecurityException`. This guarantees a sealed package is **indivisible and tamper-resistant** at the packaging level. ## How you configure it Sealing is declared entirely in `META-INF/MANIFEST.MF`, a plain-text file of `Key: value` headers organized into sections separated by blank lines. 1. **Seal the whole JAR** — put in the *main* (first) section: ``` Manifest-Version: 1.0 Sealed: true ``` Now every package in the archive is sealed. 2. **Seal one package** — add a *per-entry* section whose `Name:` is the package path (note the trailing slash): ``` Name: com/example/foo/ Sealed: true ``` 3. **Un-seal an exception** — when the whole JAR is sealed you can carve out one package: ``` Name: com/example/open/ Sealed: false ``` The most specific (per-entry) setting wins over the main-section default. ## With build tools With Maven's `maven-jar-plugin` you set `<sealed>true</sealed>` under `<manifest>`. With Gradle you add the attribute to the `jar` task's manifest: `manifest { attributes('Sealed': 'true') }`. The `jar` CLI reads attributes from a manifest you pass via `jar cfm app.jar manifest.txt ...`. ## When it actually fires Verification happens at **class-load time**, by the class loader, not at compile time and not at JAR-build time. So a sealing violation surfaces as a runtime `SecurityException` the first time a stray class of the sealed package is requested. ## Relationship to signing and to JPMS Sealing answers *“are all these classes from one JAR?”*. **JAR signing** (a separate feature) answers *“who published this JAR and has it been altered?”*. They are independent and complementary — sealing about cohesion, signing about provenance/integrity of bytes. Note that the **Java Platform Module System (JPMS, since Java 9)** offers stronger encapsulation: a module's `exports` controls which packages are visible and a *non-exported* package cannot be augmented or accessed from outside at all. Where modules are used, JPMS largely supersedes sealing for encapsulation; sealing remains a lightweight classpath-era mechanism that still works for plain (non-modular) JARs.

  • At what point is a sealing violation detected?
    At class-load time, by the class loader. The JVM throws a SecurityException the first time a class of a sealed package is requested from a different source than the one that supplied the package's first-loaded class. It is not a compile-time or build-time check.
  • How do you seal the whole JAR but leave one package open?
    Put 'Sealed: true' in the manifest's main section, then add a per-entry section 'Name: com/example/open/' with 'Sealed: false'. The per-entry setting overrides the global default for that package.

A sealed package is like a tamper-evident shrink-wrapped product box: every item inside must have come from that one sealed box. If a part shows up from a different box, you reject the whole thing as compromised.

saying these in an interview costs you the question

  • Saying sealing encrypts or signs the classes — it does neither; it only enforces single-JAR origin.
  • Confusing sealing with the 'sealed classes/interfaces' language feature (Java 17) — unrelated, that restricts which types may extend a class.
  • Claiming the check happens at compile time or when building the JAR — it is a runtime class-loader check.
  • Thinking sealing alone proves provenance/who published it — that is signing, a separate concern.

context

open as a page

Why would you sign a JAR, and what security property does a signature actually give you?

level: middleimportance: should knowfreq 30%

basics

~10 s

Signing a JAR attaches a digital signature so you can prove who published it and that nobody changed its files afterward. It gives integrity and authenticity — not secrecy.

open as a page

Walk through the practical workflow of signing and verifying a JAR with keytool and jarsigner.

level: seniorimportance: should knowfreq 28%

basics

~20 s

Use keytool to create a keypair/certificate in a keystore, then jarsigner to sign the JAR with that key. To check a JAR, run 'jarsigner -verify' which recomputes hashes and validates the signature against the certificate.

open as a page

Explain the files signing adds under META-INF — the manifest digests, the .SF file, and the .RSA/.DSA/.EC block — and how the runtime uses them to verify.

level: seniorimportance: should knowfreq 24%

basics

~20 s

Signing adds per-file hashes to MANIFEST.MF, a NAME.SF file holding a hash of the manifest, and a NAME.RSA/DSA/EC block containing the actual digital signature plus the certificate. Verification re-hashes entries and checks the signature against the certificate.

open as a page

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%

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.

open as a page