JAR File Documentation
Summary
A Java Archive (.jar) is a ZIP-format bundle of compiled Java class files, resources and a manifest, used to distribute and run desktop Java programs and libraries. Its MIME type is application/java-archive. To run an executable JAR you need Java installed, then java -jar app.jar or a double-click. Because a JAR is a ZIP, you can rename it to .zip or open it in 7-Zip to see the class files inside.
Technical details
| Feature | Value |
|---|---|
| Full name | Java Archive (JAR) |
| File extension | .jar |
| MIME type | application/java-archive |
| Format type | ZIP archive of Java bytecode, resources and a manifest |
| Container / base format | PKZIP (same structure as .zip) |
| Compression | Per-entry DEFLATE, or stored (uncompressed) |
| Developer | Sun Microsystems (now Oracle); part of the Java Platform |
| Introduced | 1996–1997 (JDK 1.1) |
| Standard / spec | JAR File Specification (Java SE technotes) |
| Open standard | Yes — documented and freely implementable |
| Byte order | Little-endian (ZIP records) |
| Magic number (hex) | 50 4B 03 04 (ASCII PK) |
| Manifest | META-INF/MANIFEST.MF — RFC 822-style name: value headers |
| Executable marker | Main-Class attribute in the manifest |
| Payload | Compiled .class files in package folders, plus resources |
| Signing files | META-INF/*.SF and META-INF/*.RSA/*.DSA (optional) |
| Runtime | Java Virtual Machine (JRE/JDK) — not a native OS executable |
| Related packaging | .war, .ear (also ZIP/JAR-based) |
| Related extensions | .zip, .class, .war, .ear, .jnlp, .apk |
| Specification | docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html |
What is a JAR file?
JAR stands for Java Archive. It is the standard packaging format for Java, introduced with JDK 1.1 in 1996–1997 by Sun Microsystems (now Oracle). A JAR bundles many files into one: the compiled .class bytecode files that make up a program or library, the resources those classes need (images, text, configuration), and a small metadata file called the manifest. Packing everything into a single archive means a whole application or library ships and loads as one unit.
Under the surface a JAR is a ZIP archive with a defined internal layout, so its MIME type is application/java-archive and it begins with the ZIP magic bytes 50 4B 03 04. A JAR is not a native program: the operating system cannot run it directly. It runs on the Java Virtual Machine, which is why you need a JRE or JDK installed and launch it with java -jar app.jar. Everything below is about what the ZIP container holds and how the runtime reads it.
The ZIP container: local headers and the central directory
Because a JAR is a ZIP, it inherits the ZIP file structure exactly. Each entry is stored as a local file header (signature 50 4B 03 04) followed by the entry’s compressed bytes. Every entry is compressed independently, almost always with DEFLATE, though small entries may be stored uncompressed. After all entries comes the central directory: a second copy of each entry’s metadata (name, sizes, CRC-32, offset) that a reader uses as an index, ending with an End of Central Directory record that a parser locates by scanning backwards from the tail of the file.
Two consequences follow. First, any ZIP tool opens a JAR: renaming app.jar to app.zip lets 7-Zip or Windows Explorer list and extract its contents. Second, per-entry compression means the JVM can read the central directory once and then seek directly to and inflate a single class on demand, without unpacking the whole archive, which is how class loading stays lazy.
META-INF/MANIFEST.MF: the manifest, header by header
What turns an ordinary ZIP into a JAR is the manifest, a text file at the fixed path META-INF/MANIFEST.MF. It uses name: value headers inspired by RFC 822, grouped into sections separated by blank lines. The first section is the main section, describing the archive as a whole; later per-entry sections can attach attributes to individual files. A minimal executable manifest looks like this:
Manifest-Version: 1.0
Created-By: 17.0.10 (Eclipse Adoptium)
Main-Class: com.example.App
Class-Path: lib/guava.jar lib/commons-io.jar
The Main-Class attribute is the one that makes a JAR runnable. It names the fully qualified class whose public static void main(String[]) method the launcher calls, so java -jar app.jar reads this header and starts there. A JAR with no Main-Class is a library JAR, meant to be added to another program’s classpath rather than launched, which is exactly why double-clicking some JARs does nothing. The Class-Path attribute lists other JARs, as relative URLs separated by spaces, that this archive depends on. One quirk of the format worth knowing: manifest lines are wrapped at 72 bytes, and a continued line begins with a single leading space, so long values are split in a specific way that hand-editing must respect.
Class files and the package-to-folder mapping
The bulk of a JAR is compiled .class files, and their location inside the archive is not arbitrary. Java maps a class’s package to a directory path: a class declared package com.example; and named App is stored at com/example/App.class. The class loader turns a requested class name straight into that path and asks the ZIP central directory for the entry. Each .class file is itself a structured binary that starts with its own magic number CA FE BA BE and carries the JVM bytecode, constant pool and method tables for one class. Alongside the classes sit resources, files such as .properties bundles, icons and configuration, which code reads at runtime through getResourceAsStream using the same archive-relative paths.
Signing: the manifest digest, the .SF file and the .RSA block
A JAR can be cryptographically signed so a consumer can verify its origin and that no entry has been altered. Signing does not repackage the archive; it adds files to META-INF/ and extends the manifest. The process has three layers:
- The manifest gains a per-entry section for each file containing a message digest (for example a SHA-256 hash) of that entry’s bytes.
- A signature file with the
.SFextension is added. It mirrors the manifest but stores digests of the manifest entries themselves, so it fixes the manifest content. - A signature block file,
.RSAor.DSAdepending on the key type, holds a PKCS#7 detached signature over the.SFfile plus the signer’s certificate chain.
At load time the JVM (or jarsigner -verify) recomputes each entry’s digest and checks it against the manifest, checks the manifest against the .SF, and checks the .SF signature against the certificate. Any tampered byte breaks the chain. A signature proves who produced the archive and that it is intact; it says nothing about whether the code is safe to run.
How the launcher runs a JAR
When you invoke java -jar app.jar, the launcher opens the archive, reads META-INF/MANIFEST.MF, and looks for Main-Class. It builds a class loader rooted at the JAR (extended by any Class-Path entries), loads the named class, and calls its main method. If the manifest has no Main-Class, the launcher errors out with “no main manifest attribute”, the classic sign of a library JAR that was never meant to be launched. A double-click works only when the operating system has associated .jar with the Java launcher (javaw on Windows); if it is associated with an archiver instead, double-clicking opens the ZIP rather than running the program. On modern systems the free choice of runtime is an OpenJDK build such as Eclipse Temurin, since Oracle’s old consumer JRE is legacy.
WAR, EAR and the J2ME MIDlet JAR
The same ZIP-plus-manifest design is reused across the Java world. A .war (Web Application Archive) packages a servlet-based web app, adding a WEB-INF/ layout; a .ear (Enterprise Archive) bundles multiple modules for a Java EE server. Both are JARs with extra structure. A separate historical meaning is worth flagging: in the 2000s, feature-phone games shipped as J2ME MIDlet JARs paired with a small .jad text descriptor. Those target the phone’s Java ME profile, not desktop Java, so a MIDlet JAR will not launch on a PC with java -jar; it needs a J2ME emulator such as FreeJ2ME. That is why an old “JAR game” refuses to run even with a normal JDK installed.
Is a JAR file safe to run?
The risk is real and comparable to an .exe. A runnable JAR is a full program: once Java is installed, java -jar executes whatever bytecode the archive contains, with your user account’s permissions and no sandbox. Java remote-access trojans and downloaders are a known malware family precisely because a single cross-platform JAR runs anywhere a JVM does. The mechanics of the danger are ordinary code execution, not an exploit: the manifest names a Main-Class, the launcher calls it, and that code can touch files, the network and the system like any application. Merely inspecting a JAR as a ZIP in 7-Zip is safe because nothing is executed; running it is the risk. Treat an unsolicited .jar attachment exactly as you would an unknown executable, and remember that a valid signature proves origin, not good intent.
Frequently asked questions
Why does double-clicking my JAR do nothing?
Three common causes. Java may not be installed, so there is no launcher to invoke; the .jar extension may be associated with an archiver (7-Zip, WinRAR) rather than the Java launcher, so it opens as a ZIP; or the JAR may be a library with no Main-Class in its manifest and therefore has nothing to run. Test from a terminal with java -jar app.jar: a “no main manifest attribute” error confirms the third case.
A JAR holds .class files, so can I get the Java source back?
Not exactly. Extract the archive to obtain the .class bytecode, then run a decompiler such as JD-GUI or CFR to reconstruct approximate Java source. Decompiled output is readable but not identical to the original: comments are gone, local variable names may be synthesised, and obfuscated code can be hard to follow. It is an approximation, not the author’s source file.
References
- Oracle — JAR File Specification
- Oracle — Signed JAR File (manifest, .SF and signature block)
- Eclipse Adoptium (Temurin OpenJDK) — downloads
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.