Recent from talks
Nothing was collected or created yet.
JAR (file format)
View on Wikipedia| Java Archive | |
|---|---|
![]() KDE JAR file icon | |
| Filename extension | .jar |
| Internet media type | |
| Uniform Type Identifier (UTI) | com.sun.java-archive |
| Magic number | 50 4b 03 04 ASCII:PK\x03\x04 |
| Developed by | Netscape, Sun Microsystems, Oracle Corporation |
| Type of format | File archive, data compression |
| Extended from | ZIP |
A JAR ("Java archive") file is a package file format typically used to aggregate many Java class files and associated metadata and resources (text, images, etc.) into one file for distribution.[4]
JAR files are archive files that include a Java-specific manifest file. They are built on the ZIP format and typically have a .jar file extension.[5]
Design
[edit]A JAR file allows Java runtimes to efficiently deploy an entire application, including its classes and their associated resources, in a single request. JAR file elements may be compressed, shortening download times.
A JAR file may contain a manifest file, that is located at META-INF/MANIFEST.MF. The entries in the manifest file describe how to use the JAR file. For instance, a Classpath entry can be used to specify other JAR files to load with the JAR.
Extraction
[edit]The contents of a file may be extracted using any archive extraction software that supports the ZIP format, or the
jar command line utility provided by the Java Development Kit.
Security
[edit]Developers can digitally sign JAR files. In that case, the signature information becomes part of the embedded manifest file. The JAR itself is not signed, but instead every file inside the archive is listed along with its checksum; it is these checksums that are signed. Multiple entities may sign the JAR file, changing the JAR file itself with each signing, although the signed files themselves remain valid. When the Java runtime loads signed JAR files, it can validate the signatures and refuse to load classes that do not match the signature. It can also support 'sealed' packages, in which the Classloader will only permit Java classes to be loaded into the same package if they are all signed by the same entities. This prevents malicious code from being inserted into an existing package, and so gaining access to package-scoped classes and data.
The content of JAR files may be obfuscated to make reverse engineering more difficult.
Executable JAR files
[edit]An executable Java program can be packaged in a JAR file, along with any libraries the program uses. Executable JAR files have the manifest specifying the entry point class with Main-Class: myPrograms.MyClass and an explicit Class-Path (and the -cp argument is ignored). Some operating systems can run these directly when clicked. The typical invocation is java -jar foo.jar from a command line.
Native launchers can be created on most platforms. For instance, Microsoft Windows users who prefer having Windows EXE files can use tools such as JSmooth, Launch4J, WinRun4J or Nullsoft Scriptable Install System to wrap single JAR files into executables.
Manifest
[edit]A manifest file is a metadata file contained within a JAR.[6][7] It defines extension and package-related data. It contains name–value pairs organized in sections. If a JAR file is intended to be used as an executable file, the manifest file specifies the main class of the application. The manifest file is named MANIFEST.MF. The manifest directory has to be the first entry of the compressed archive.
Specifications
[edit]The manifest appears at the canonical location META-INF/MANIFEST.MF.[8] There can be only one manifest file in an archive and it must be at that location.
The content of the manifest file in a JAR file created with version 1.0 of the Java Development Kit is the following.
Manifest-Version: 1.0
The name is separated from its value by a colon. The default manifest shows that it conforms to version 1.0 of the manifest specification.
The manifest can contain information about the other files that are packaged in the archive. Manifest contents depend on the intended use for the JAR file. The default manifest file makes no assumptions about what information it should record about other files, so its single line contains data only about itself. It should be encoded in UTF-8.
Special-Purpose Manifest Headers
[edit]JAR files created only for the purpose of archiving do not use the MANIFEST.MF file.
Most uses of JAR files go beyond simple archiving and compression and require special information in the manifest file.
Features
[edit]The manifest allows developers to define several useful features for their jars. Properties are specified in key-value pairs.
Applications
[edit]If an application is contained in a JAR file, the Java Virtual Machine needs to know the application's entry point. An entry point is any class with a public static void main(String[] args) method. This information is provided in the manifest Main-Class header, which has the general form:
Main-Class: com.example.MyClassName
In this example com.example.MyClassName.main() executes at application launch.
Package Sealing
[edit]Optionally, a package within a JAR file can be sealed, which means that all classes defined in that package are archived in the same JAR file. A package might be sealed to ensure version consistency among the classes in the software or as a security measure.
To seal a package, a Name entry needs to appear, followed by a Sealed header, such as:
Name: myCompany/myPackage/
Sealed: true
The Name header's value is the package's relative pathname. Note that it ends with a '/' to distinguish it from a filename. Any headers following a Name header, without any intervening blank lines, apply to the file or package specified in the Name header. In the above example, because the Sealed header occurs after the Name: myCompany/myPackage header with no intervening blank lines, the Sealed header applies (only) to the package myCompany/myPackage.
The feature of sealed packages is outmoded by the Java Platform Module System introduced in Java 9, in which modules cannot split packages.[9]
Package Versioning
[edit]Several manifest headers hold versioning information. One set of headers can be assigned to each package. The versioning headers appear directly beneath the Name header for the package. This example shows all the versioning headers:
Name: java/util/
Specification-Title: "Java Utility Classes"
Specification-Version: "1.2"
Specification-Vendor: "Sun Microsystems, Inc.".
Implementation-Title: "java.util"
Implementation-Version: "build57"
Implementation-Vendor: "Sun Microsystems, Inc."
Multi-Release
[edit]A jar can be optionally marked as a multi-release jar. Using the multi-release feature allows library developers to load different code depending on the version of the Java runtime.[10] This in turn allows developers to leverage new features without sacrificing compatibility.
A multi-release jar is enabled using the following declaration in the manifest:
Multi-Release: true
Dependencies
[edit]The MANIFEST.MF file can be used to specify all the classes that must be loaded for an application to be able to run.[11]
Note that Class-Path entries are delimited with spaces, not with the system path delimiter:
Class-Path: . pkg1.jar path/to/pkg2.jar
Apache Ant Zip/JAR support
[edit]The Apache Ant build tool has its own package to read and write Zip and JAR archives, including support for Unix filesystem extensions. The org.apache.tools.zip package is released under the Apache Software Foundation license and is designed to be usable outside Ant.
Related formats
[edit]Several related file formats build on the JAR format:
- WAR (Web application archive) files, also Java archives, store XML files, Java classes, JavaServer Pages and other objects for Web Applications.
- RAR (resource adapter archive) files (not to be confused with the RAR file format), also Java archives, store XML files, Java classes and other objects for J2EE Connector Architecture (JCA) applications.
- EAR (enterprise archive) files provide composite Java archives that combine XML files, Java classes and other objects including JAR, WAR and RAR Java archive files for Enterprise Applications.
- SAR (service archive) is similar to EAR. It provides a
service.xmlfile and accompanying JAR files. - APK (Android application package), a variant of the Java archive format, is used for Android applications.[12]
- AAR (Android archive) is used for distribution of Android libraries, typically via Maven.[13]
- PAR (plan archive) – supported by Eclipse Virgo OSGi application server, allows the deployment of multi-bundle OSGi applications as a single archive and provides isolation from other PAR-based applications deployed in the same server.
- KAR (Karaf archive) – supported by Apache Karaf OSGi application server, allows the deployment of multi-bundle, multi-feature OSGi applications.
See also
[edit]References
[edit]- ^ "File Extension .JAR Details". Retrieved 29 November 2012.
- ^ "MIME : Java Glossary". Retrieved 29 November 2012.
- ^ "IANA Assignment". Retrieved 12 May 2023.
- ^ "JDK 6 Java Archive (JAR)-related APIs & DeveloperGuides".
- ^ "JAR File Specification". Java SE Documentation. Oracle. Archived from the original on 2017-09-11.
- ^ "Understanding the Manifest". Java.sun.com. 2003-03-21. Retrieved 2012-07-31.
- ^ "JAR File Specification". Download.oracle.com. Retrieved 2012-07-31.
- ^ "JAR File Specification". Download.oracle.com. Retrieved 2012-07-31.
- ^ "JEP 261: Module System". Retrieved 2021-02-06.
- ^ "JEP 238: Multi-Release JAR Files". Retrieved 2021-02-06.
- ^ the sun servlet specification, page 72 (servlet-2_4-fr-spec.pdf). See also the Java Tech Notes.
- ^ "Glossary". developer.android.com.
- ^ "Android library". developer.android.com.
External links
[edit]JAR (file format)
View on Grokipediajava -jar command or by double-clicking on supported systems, making them a standard for distributing Java software.[2] They also support advanced features like package sealing to prevent class loading from multiple sources and indexing for faster multi-JAR loading.[3]
Overview
Definition and Purpose
The JAR (Java Archive) file format is a platform-independent archive standard based on the ZIP file format, designed to aggregate Java class files, associated metadata, resources such as images and sounds, and an optional manifest file into a single distributable package.[1][2] This structure allows developers to bundle related components of Java applications or libraries efficiently, ensuring compatibility across different Java Virtual Machine (JVM) implementations and operating systems.[8] The primary purposes of the JAR format include facilitating the packaging of Java classes for both standalone applications and reusable libraries, enabling straightforward distribution via a single file that can be downloaded or shared with minimal overhead.[1] It supports Java's core principle of portability by allowing the same archive to run unchanged on any platform with a compatible JVM, and it was particularly instrumental in the early deployment of applets by combining multiple files—including classes, resources, and HTML—into one unit for faster network transfers.[8][9] Key benefits of JAR files encompass built-in compression to reduce file sizes and accelerate downloads, as well as the ability to create self-contained packages that incorporate version information and digital signatures to verify integrity and authenticity against tampering.[1][8] The format was introduced in the Java Development Kit (JDK) 1.1 in 1997 as a more robust alternative to earlier, ad-hoc methods of packaging Java classes, such as loose file collections or simple ZIP usage without standardized metadata support.[10][9]History and Evolution
The JAR (Java ARchive) file format was developed by Sun Microsystems and introduced in 1997 with JDK 1.1 to bundle Java classes, images, sounds, and other resources into a single, compressed archive, primarily to streamline the distribution of applets over the web.[10] This addressed early Java challenges in applet loading by enabling a single HTTP transaction via theARCHIVE attribute in the <APPLET> tag, reducing download times and supporting platform-independent packaging based on the ZIP format.[1] JDK 1.1 also incorporated an optional manifest file (META-INF/MANIFEST.MF) to provide metadata such as versioning information, allowing developers to specify attributes for packages and entries within the archive.
Subsequent enhancements focused on security and tooling. In 1998, JDK 1.2 integrated digital signing capabilities for JAR files using the jarsigner tool, permitting signed content to grant applets extended permissions beyond the default sandbox while maintaining integrity verification, and introduced package sealing via the Sealed manifest attribute to ensure all classes in a package originate from the same JAR.[11][3] JDK 1.3 in 2000 included further refinements to the jar utility. By Java 5 in 2004, manifest metadata was expanded with richer versioning schemes, facilitating more robust application deployment.[3]
The format's evolution reflects responses to web deployment needs, security requirements, and modular programming paradigms. Java 9 in 2017 introduced multi-release JARs via JEP 238, allowing a single archive to include version-specific classes (e.g., in META-INF/versions/{n}/) for compatibility across Java releases without duplicating artifacts.[12] Java 11 in 2018, as the first long-term support (LTS) release post-JPMS, standardized modular JARs with module-info.class descriptors at the root, enhancing encapsulation and explicit dependencies in the Java Platform Module System.[13] As of 2025, JARs continue to play a key role in modular applications and containerized environments, such as Docker-based deployments of executable "fat" JARs in frameworks like Spring Boot.[14]
Technical Design
File Structure
A JAR file follows the ZIP archive format, consisting of a sequence of local file headers, compressed or uncompressed file data, optional data descriptors, and a central directory at the end that indexes all entries.[3][15] Each local file header precedes its corresponding file data and provides essential metadata, while the central directory contains a consolidated list of headers for efficient access. By default, JAR files employ DEFLATE compression for entries, though uncompressed storage is also supported.[3][15] Entries within a JAR file primarily include compiled Java bytecode in.class files, optional source code in .java files, and various resources such as images, properties files, or other non-executable data. An optional META-INF/ directory houses the manifest file (MANIFEST.MF) and optional signature files for integrity verification.[3] These entries are stored without absolute file system paths, adhering strictly to Java packaging conventions.
Each entry begins with a 30-byte local file header, structured as follows:
| Byte Offset | Size (bytes) | Field | Description |
|---|---|---|---|
| 0 | 4 | Signature | Fixed value 0x04034b50 identifying the local header. |
| 4 | 2 | Version Needed to Extract | ZIP specification version required (typically 2.0 or higher for DEFLATE). |
| 6 | 2 | General Purpose Bit Flag | Flags indicating compression options, encryption, or data descriptor usage. |
| 8 | 2 | Compression Method | 0 for uncompressed; 8 for DEFLATE (default in JAR). |
| 10 | 2 | Last Modified Time | File modification time in DOS format. |
| 12 | 2 | Last Modified Date | File modification date in DOS format. |
| 14 | 4 | CRC-32 | 32-bit checksum for data integrity verification. |
| 18 | 4 | Compressed Size | Length of compressed data (0 if uncompressed). |
| 22 | 4 | Uncompressed Size | Original length of the file data. |
| 26 | 2 | File Name Length | Length of the subsequent file name field. |
| 28 | 2 | Extra Field Length | Length of optional extra field for additional metadata. |
com.example package appears as com/example/MyClass.class. This convention ensures no extraneous file system paths are included, maintaining portability across platforms.[3]
Due to its ZIP heritage, each entry in a JAR file has a theoretical maximum size of 4 GB for both compressed and uncompressed data under the standard ZIP specification, though practical limitations arise from Java Virtual Machine (JVM) memory constraints and implementation details. However, the ZIP64 extension, supported since Java 7, allows individual entries and the overall archive to exceed 4 GB.[15][3][16]
Relationship to ZIP Format
The JAR (Java Archive) file format is fundamentally based on the ZIP file format, specifically adhering to the ZIP 2.0 specification as defined by PKWARE, ensuring full backward compatibility such that any standard ZIP-compatible tool can open and extract a JAR file without issues.[3] This compatibility stems from JAR's use of the same core structure, including ZIP's central directory, local file headers, and data descriptors, allowing seamless interoperability for basic archiving operations.[3] JAR files created with Java tools support Unicode filenames by encoding them in UTF-8 and setting the appropriate ZIP general purpose bit flag. To meet Java's requirements, the JAR format introduces specific extensions beyond plain ZIP, most notably the META-INF directory containing a manifest file (MANIFEST.MF) that provides metadata like package versions, main class specifications, and permissions.[3] Additionally, JAR supports digital signing through auxiliary files in META-INF, such as .SF (signature files) for digests and .RSA or .DSA files for public-key certificates, enabling integrity verification and authenticity in Java's security model.[3] Unlike certain ZIP variants that permit encryption (e.g., via traditional ZIP 2.0 methods or later extensions like WinZip AES), JAR omits built-in encryption support to align with Java's preference for explicit security mechanisms, such as code signing, rather than obscuring contents.[3] JAR files use the Deflate algorithm (ZIP compression method 8) by default, though uncompressed entries are also supported, which is the default for both formats but not mandatory in JAR to optimize for Java's distribution needs.[3][15] Key differences further tailor JAR to Java ecosystems: it includes Java-specific manifest attributes for version information and sealing packages, while directories are handled implicitly through hierarchical entry names derived from Java package structures (e.g., com/example/MyClass.class implies a com/example/ package path) rather than requiring explicit directory entries as in some ZIP usages.[3] JAR files can contain arbitrary non-Java content, such as images or properties files, but are optimized for Java bytecode (.class files) and associated resources, with tools like unzip able to extract contents but unable to interpret or validate Java metadata like the manifest.[3] Historically, ZIP was selected for JAR due to its status as an open, non-proprietary standard with proven compression efficiency, which facilitated faster downloads for Java applets over the early web by bundling multiple files into a single archive.[1][17]Creation and Manipulation
Building JAR Files
JAR files are primarily built using thejar command-line tool included in the Java Development Kit (JDK), which packages compiled Java class files, resources, and metadata into a single archive. The basic syntax for creating a JAR file is jar cf jar-file input-file(s), where c specifies creation of a new archive, f directs output to a specified file rather than standard output, jar-file is the desired name of the output JAR (e.g., myapp.jar), and input-file(s) lists the files or directories to include, added recursively if directories are specified.[18][19]
Key options enhance the building process: -v or --verbose provides detailed output listing each added file for monitoring; -m or --manifest includes a pre-existing manifest file (e.g., jar cmf myapp.jar manifest.mf input-files) to embed metadata like version or main class, as detailed in the manifest specifications; and -C changes to a specified directory before including files, useful for packaging from build outputs without preserving the full path (e.g., jar cf myapp.jar -C build/classes . to include all classes from a compiled directory). Inclusion supports wildcards like *.class to target specific file types, while exclusion is handled by selective listing rather than a dedicated flag, ensuring only necessary elements like compiled classes and resources are packaged to optimize size.[18][19]
| Option | Description | Example Usage |
|---|---|---|
c or --create | Creates a new JAR archive. | jar c ... |
f or --file | Outputs to the specified file. | jar cf myapp.jar ... |
v or --verbose | Lists files as they are added. | jar cvf myapp.jar *.class |
m or --manifest | Includes a manifest file. | jar cmf myapp.jar manifest.mf ... |
-C | Changes directory for inclusion. | jar cf myapp.jar -C src/classes . |
java.util.jar.JarOutputStream class extends ZipOutputStream to write JAR entries dynamically to an output stream, supporting manifest addition via JarOutputStream(Manifest) constructor and entry addition with putNextEntry(JarEntry). This API allows runtime assembly, such as bundling resources based on application logic, by iterating over files and writing their contents compressed or uncompressed as needed.
Best practices for building JAR files emphasize organizing contents to mirror Java package structures (e.g., com/example/Main.class under a root directory) to preserve class paths, including only essential compiled classes, resources, and manifests to minimize archive size and improve load times, and verifying the result with jar tf myapp.jar to list contents without extraction. Manifest inclusion during builds can specify attributes like package versions, but full details are covered in manifest specifications.[18]
Automation of JAR building is commonly achieved through integration with build tools like Apache Maven's JAR plugin, which binds to the package lifecycle phase to reproducibly compile, package classes and resources into a JAR, and customize outputs via pom.xml configurations such as <finalName> for naming or <excludes> for filtering files, ensuring consistent builds across environments.[20][21]
Extracting and Viewing Contents
JAR files can be extracted and viewed using the command-linejar tool provided in the Java Development Kit (JDK). The extraction operation uses the x option, such as jar xf myapp.jar, which unpacks all contents of the specified archive to the current directory.[22] For verbose output during extraction, the v option is added, as in jar xvf myapp.jar, displaying each file as it is processed.[22] Selective extraction is supported by specifying paths or filenames after the archive, for example, jar xf myapp.jar com/example/, which extracts only the contents of the com/example/ directory.[22]
To view the contents of a JAR file without extracting it, the t option lists the table of contents, such as jar tf myapp.jar, outputting the names of all entries in the archive.[22] Adding the v option provides detailed information, including file sizes, compression methods, and modification dates, as with jar tvf myapp.jar.[22] These listing operations allow quick inspection of the archive's structure, such as verifying the presence of class files or resources.
Programmatic access to JAR contents is facilitated by the java.util.jar.JarFile class, which extends java.util.zip.ZipFile to support JAR-specific features like manifest reading.[23] Key methods include getEntry(String name), which retrieves a JarEntry for a specified path, returning null if not found, and getInputStream(ZipEntry entry), which provides a stream for reading the entry's data.[23] The entries() method returns an enumeration of all JarEntry objects, enabling iteration over the archive, while the class supports random access via underlying RandomAccessFile for efficient non-sequential reading.[23]
Third-party tools compatible with the ZIP format can also handle JAR files. The unzip command-line utility lists contents with unzip -l myapp.jar and extracts them using unzip myapp.jar, preserving file permissions and timestamps where supported by the ZIP standard. Graphical tools like 7-Zip allow GUI-based extraction by opening the JAR file and selecting files or directories, maintaining metadata such as timestamps during the process.[24]
These methods are commonly used for debugging classpaths by inspecting dependencies, verifying build outputs through content listings, or integrating extraction into automation scripts for deployment pipelines.[22]
Manifest Configuration
Format and Core Specifications
The manifest file within a JAR archive is always located at the pathMETA-INF/MANIFEST.MF and is encoded in UTF-8 text format. It is structured as a sequence of lines, where each logical entry (such as an attribute or section delimiter) terminates with a newline sequence, which can be CR LF, LF alone, or CR not followed by LF. The file must begin with a main section that includes a required version header, specified as Manifest-Version: 1.0, placed as the first line to indicate the manifest format version. This header establishes the baseline compatibility for the manifest's syntax and semantics.[25]
The syntax of the manifest employs a simple key-value pair structure inspired by RFC 822 headers, consisting of lines in the form Name: value, where attribute names are case-insensitive, and values are restricted to a maximum of 72 bytes (in UTF-8 encoding) per line to ensure portability. Continuation lines for longer values begin with a single space character followed by the remaining text, allowing seamless extension without altering the attribute semantics. The manifest divides into a main section for global attributes applicable to the entire JAR—terminated by a blank line—and optional per-entry sections, each initiated by a Name: attribute specifying the relative path (or URL) of a particular file or directory within the archive. These per-entry sections inherit and can override main section attributes for targeted metadata. No Name: attribute is permitted in the main section itself. Attribute names must not exceed 70 bytes (excluding the colon and any following space), and they cannot contain NUL, CR, LF, or colon characters to maintain parsability.[25]
At its core, the manifest serves as a metadata container for defining JAR identity, package versioning, and execution parameters, enabling critical functionalities such as digital signing and self-contained application deployment; it is mandatory for signed JARs to support integrity verification and for executable JARs to specify entry points. The format is formally defined in Oracle's JAR File Specification, an integral component of the Java SE platform, with the foundational 1.0 version introduced in JDK 1.1 and subsequent refinements added across JDK releases to accommodate evolving platform needs, such as multi-release support in later versions.[25]
Manifest parsing is performed on a line-by-line basis by the Java runtime, treating the file as case-insensitive for attribute names while preserving value content exactly. Invalid structures, such as malformed headers, missing version lines, or non-compliant line endings, trigger parsing warnings during JAR verification and may render signatures untrusted, potentially causing runtime failures like inability to load executable components or verify contents. The java.util.jar.Manifest class in the Java API handles reading and writing, throwing IOException for I/O-related parsing errors but relying on the specification's grammar for structural validation.[25][26]
Standard Attributes
The standard attributes in a JAR manifest file provide essential metadata about the archive's creation, structure, and basic runtime behavior, residing in the main section of the manifest (META-INF/MANIFEST.MF). These attributes are defined in the main attributes block and influence how the Java Virtual Machine (JVM) loads and executes the JAR. They follow a simple key-value format, with values being UTF-8 encoded strings, and are optional unless specified otherwise for certain functionalities.[25] Manifest-Version is the mandatory first attribute, specifying the version of the manifest format to which the JAR conforms, "1.0". This attribute ensures compatibility with the JVM's manifest parser, which expects it at the start of the main section; absence or malformation can lead to parsing errors during loading.[25][27] Created-By indicates the tool and version used to generate the JAR file, such as "1.8.0_XXX (Oracle Corporation)" when built with the standardjar tool. This attribute is automatically added by the jar command and serves primarily for debugging and provenance tracking, helping developers identify the build environment without affecting runtime behavior.[25]
Main-Class defines the fully qualified name of the application's entry point class for executable JARs, for example, "com.example.Main". When the JVM invokes java -jar file.jar, it locates and instantiates this class's main method, enabling standalone execution; the attribute must be in the main section and point to a valid class within the JAR.[25][27]
Class-Path extends the JVM's classpath by listing relative URLs to external JARs or directories, separated by spaces, such as "lib/helper.jar anotherlib.jar". The application class loader appends these paths lazily during class resolution, allowing modular dependencies without embedding all code in a single archive; paths are resolved relative to the JAR's location at runtime.[25][27]
The Implementation- attributes provide package-level identification for libraries and extensions, including Implementation-Title (a descriptive name, e.g., "My Utility Library"), Implementation-Version (a version string, e.g., "1.0.0"), Implementation-Vendor (the provider, e.g., "Example Corp."), and Implementation-Vendor-Id (a unique identifier, e.g., "com.example"). These are placed in the main section or per-entry sections for specific packages and aid in version management and dependency resolution by the JVM's class loader, though they do not enforce loading behavior directly.[25][27]
Advanced Manifest Features
Special-Purpose Headers
Special-purpose headers in the JAR manifest file provide functionality for advanced features such as digital signing and extension mechanisms, enabling specific behaviors during verification or loading. These headers are typically used in the main section or per-entry sections of the manifest and are not part of the standard attributes required for basic JAR operation. They support niche use cases like secure distribution and historical plugin-like extensibility, though some have been deprecated in modern Java versions. The Signature-Version header indicates the version of the signing format used in a signed JAR file, with the value "1.0" being the standard for JAR signing.[3] This header must appear first in the main manifest section after Manifest-Version and is accompanied by signature files in the META-INF directory, such as .SF files containing digests of the manifest and individual entries (e.g., SHA-256-Digest-Manifest and per-entry digests) and .RSA or .DSA files holding the digital signature of the .SF file in a PKCS#7 structure.[3] The PKCS#7 format encapsulates the signed data, allowing verification of the JAR's integrity and authenticity without altering the archive contents.[3] These signing headers play a key role in security by enabling the Java runtime to validate code provenance before execution.[3] The Magic header is an optional per-entry attribute that specifies comma-separated, case-insensitive strings (e.g., "JavaScript, Dynamic" or "Multilingual") to guide the verifier on how to compute digest values for signature validation of non-standard content.[3] It addresses challenges in hashing dynamic or context-specific data, such as embedded scripts or multiple language variants, ensuring accurate integrity checks during signed JAR verification.[3] Historically introduced for advanced signing scenarios in early Java versions, this header is rarely used post-Java 1.1 due to evolving verification standards.[3] Headers related to the JAR extension mechanism, such as Extension-List, Extension-Name, Extension-Installation, and Extension-Relocation, facilitate the loading of optional extensions as plugin-like modules in applets or applications.[3] Extension-List enumerates required extensions in the main section, while Extension-Name provides a unique identifier (e.g., in the formatPackage Sealing and Versioning
Package sealing in JAR files allows developers to ensure that all classes within a specific package originate from the same JAR archive, thereby maintaining package integrity and preventing unauthorized modifications or extensions at runtime. This feature is configured using theSealed attribute in the manifest file, which can be set to true or false (case-insensitive). When applied in the main section of the manifest, Sealed: true seals all packages in the JAR unless overridden by per-package entries; conversely, Sealed: false unseals them. Per-package sealing is achieved by creating dedicated sections in the manifest starting with a Name attribute specifying the package path (e.g., Name: com/example/mypackage/), followed by Sealed: true to seal that package individually.[7]
Unsealing is handled selectively for extensible packages by setting Sealed: false in a per-package manifest section, allowing classes from that package to be loaded from multiple JARs without violating integrity checks. This approach is useful for frameworks or libraries that permit extensions while protecting other sealed components. The Java Virtual Machine (JVM) enforces sealing during class loading: if a sealed package's classes are found in different JARs, a SecurityException is thrown, ensuring runtime consistency.[7]
Versioning in JAR manifests provides metadata to distinguish between specification and implementation details of packages, facilitating compatibility checks in multi-version environments. Specification-level attributes include Specification-Title for the specification's human-readable title, Specification-Version for its version string, and Specification-Vendor for the maintaining organization; these define the API contract and apply to the package's interface. Implementation-level attributes such as Implementation-Title, Implementation-Version, and Implementation-Vendor describe the specific runtime variant, along with optional Implementation-Build for build details. These attributes can be set JAR-wide or per-package via Name sections, but the JVM does not enforce them— they serve as informational aids for tools and developers.[7]
These features were introduced in JDK 1.2 to support robust packaging in distributed Java applications.[3] In signed JARs, sealing enhances security by preventing post-build class additions that could tamper with verified content, while versioning helps manage dependencies across different implementation variants without conflicts.[7]
Executable JARs
Configuration Requirements
To configure a JAR file as executable, the manifest must include theMain-Class attribute, which specifies the fully qualified name of the class containing the public static void main(String[] args) method that serves as the application's entry point.[29] This attribute is mandatory for the java -jar command to identify and invoke the starting class; without it, execution fails with an error indicating no main manifest attribute.[29] Optionally, the Class-Path attribute can list relative URLs to external JARs or directories containing dependencies, separated by spaces, allowing the JVM to extend the classpath automatically during launch.[30]
The build process involves using the jar tool to create the archive while setting the entry point. For example, the command jar cfe myapp.jar MainClass -C build/classes . creates an executable JAR named myapp.jar, specifies MainClass as the entry point (overriding or adding the Main-Class attribute), changes to the build/classes directory to include compiled classes, and adds all files from the current directory.[22] This ensures the manifest is properly configured during packaging, avoiding manual editing of the META-INF/MANIFEST.MF file, which must end with a newline for correct parsing.[31]
Standard executable JARs rely on an external classpath for dependencies, requiring users to manage separate JAR files as specified in the Class-Path attribute, which can complicate distribution.[30] In contrast, fat JARs (also known as uber-JARs) embed all dependencies directly into a single archive, simplifying deployment by eliminating external references; this is achieved using build tools like the Maven Shade Plugin, which merges classes and resources while handling potential conflicts such as duplicate packages. Verification of the configuration involves attempting java -jar myapp.jar, which will fail if the Main-Class is missing or incorrect, confirming the manifest's integrity before distribution.[29]
Executable JARs are limited to pure Java bytecode for the main class and core logic, as they rely on the JVM for execution and do not natively support compiled native code without additional JNI loading mechanisms, which require platform-specific libraries outside the JAR structure.[32]
Execution and Classpath Handling
Executable JAR files are invoked using thejava -jar command, which specifies the path to the JAR file containing the application's entry point. This command automatically configures the classpath to include the JAR file itself and any additional entries listed in the Class-Path attribute of its manifest file, if present. The Java Virtual Machine (JVM) then loads the class specified in the Main-Class manifest attribute and executes its main method, enabling the application to run without needing to explicitly provide the main class name on the command line.[7]
When using java -jar, the classpath resolution begins with the executable JAR as the base, and relative paths in the manifest's Class-Path attribute are resolved from the location of the JAR file. For example, if the JAR is located at /app/myapp.jar and the manifest includes Class-Path: lib/helper.jar config/, the JVM will look for helper.jar in /app/lib/ and resources in /app/config/. These paths support directories and other JAR files but do not allow wildcards within the manifest attribute itself; however, wildcards such as * are supported in command-line classpath specifications starting from Java 6, for instance, java -cp "lib/*" MyClass to include all JARs in the lib directory. The command-line -cp or -classpath option overrides the manifest's Class-Path entirely, allowing custom classpath definitions that take precedence during execution. This setup enables handling of multi-JAR dependencies by chaining the listed libraries in the order specified, with the JVM loading classes on demand without issues related to bootstrap class loading for standard application dependencies.[7][33][34]
Common runtime issues during execution include the NoClassDefFoundError, which arises if a required class cannot be found due to invalid or missing classpath entries, such as a dependent JAR not being present at the expected relative path. To diagnose such problems, the -verbose:class option can be used with the java -jar command, providing detailed output on class loading attempts, including the paths searched and any failures encountered. For instance, running java -verbose:class -jar myapp.jar logs messages like "[Loaded java.lang.Object from /path/to/jre/lib/rt.jar]" to help identify missing dependencies.[35][36]
In Java 9 and later versions, the introduction of the module system distinguishes between JARs placed on the traditional classpath and those on the module path. Non-modular executable JARs continue to use java -jar with classpath resolution as described, treating them as part of the unnamed module. Modular JARs, however, are typically executed using java --module /path/to/jar/module.name when on the module path, where dependencies are resolved via explicit module declarations rather than classpath entries, though java -jar can still work for modular JARs if the module provides a main class. This separation enhances encapsulation but requires careful configuration to avoid classpath-module interoperability issues.[7]
Security Aspects
Common Vulnerabilities
One significant vulnerability in JAR files arises from unsafe deserialization of objects, particularly when applications load untrusted JARs containing serialized data processed via ObjectInputStream. This can enable remote code execution (RCE) if malicious gadgets—sequences of classes from libraries within the JAR—trigger arbitrary code during reconstruction of the object graph. For instance, attackers craft serialized payloads exploiting common libraries like Apache Commons Collections to invoke system commands.[37][38] Signature-related issues in JARs allow bypassing integrity checks, enabling tampering with contents. Weak or absent digital signatures in the JAR's META-INF directory permit attackers to modify bytecode without detection, as the jarsigner tool in older Java versions failed to properly validate signing mechanisms. A notable example is CVE-2013-4578, where attackers injected unsigned bytecode into signed JARs, compromising code-signing protections. More recently, CVE-2024-38807 demonstrated forgery in nested JARs used by frameworks like Spring Boot, where extraction disrupts signature verification chains.[39][40][41] Path traversal attacks, known as Zip Slip, exploit JAR extraction due to its ZIP-based structure. Malicious entries with relative paths like "../evil.class" can overwrite files outside the intended directory during unpacking, potentially leading to RCE if critical system files are replaced. This affects Java applications that extract JARs without validating entry paths, as seen in vulnerable code using ZipInputStream without sanitization.[42] Legacy executable JARs used in Java applets pose risks through sandbox bypass via signed code privileges. Signed JARs granted elevated permissions outside the sandbox, allowing exploits to access local resources or execute native code if the signature was trusted. These issues were prevalent in the 2010s, with attackers using social engineering to prompt users for privileges. Applets and their associated JAR handling were deprecated in Java 9 due to these persistent security flaws.[43][44] Supply chain risks emerge when the Class-Path manifest attribute references untrusted external URLs, potentially leading to dependency confusion where malicious JARs are loaded in place of legitimate ones. This can introduce tampered dependencies during runtime, exacerbating RCE or data exfiltration if the referenced resources are remotely hosted without verification. Historical incidents in the 2010s highlight these patterns, such as CVE-2010-0094, where deserialization flaws in JAR-based applets enabled RCE via remote method invocation without authentication. Similarly, CVE-2013-4578 underscored signing bypasses, affecting widespread Java deployments. These vulnerabilities, often tied to untrusted JAR loading, prompted enhanced security in later Java versions.[39][37]Best Practices and Mitigation
To enhance the security of JAR files, developers should digitally sign them using thejarsigner tool, which integrates with keystores to apply cryptographic signatures that ensure authenticity and integrity. The process involves generating a private key in a keystore (e.g., via keytool) and then executing jarsigner -keystore keystore.jks -storepass password alias myjar.jar, where alias refers to the key entry. This prevents tampering, as any modification invalidates the signature. Verification can be performed with jarsigner -verify myjar.jar, which checks the digital signatures and reports if the JAR is signed by a trusted certificate and unmodified. Oracle recommends this for all distributable JARs to protect against substitution attacks.
For validation, JAR files should be scanned for deserialization vulnerabilities, a common entry point for remote code execution, using specialized tools such as the Java Serial Killer Burp Suite extension, which generates and tests ysoserial payloads to identify exploitable serialized objects. Additionally, employing sealed packages in the JAR manifest—via the Sealed: true attribute for specific packages—ensures that all classes in a package reside within the same JAR, preventing unauthorized extensions or injections that could introduce malicious code. This sealing mechanism, defined in the JAR specification, enforces package integrity at load time.
In distribution, JAR files should be hosted exclusively on trusted repositories like Maven Central, which enforces PGP signatures, malware scanning, and publisher verification to minimize supply chain risks. Developers must avoid specifying dynamic Class-Path entries in the manifest that reference external or user-controlled paths, as this can enable loading of untrusted dependencies and amplify classpath poisoning attacks; instead, use build tools like Maven or Gradle to manage static dependencies. Whenever feasible, prefer Java modules (introduced in Java 9) over legacy JARs, as modules provide stronger encapsulation through explicit exports and access controls, reducing unintended exposure of internal APIs and enhancing overall application isolation. The Java Security Manager, previously used for fine-grained access controls, was deprecated in Java 17 and permanently disabled in JDK 24 (March 2025), so applications should rely on module boundaries and other modern security features for code isolation.[45]
For further isolation, containerize JAR-based applications using Docker, running them as non-root users with minimal base images (e.g., openjdk:17-jre-slim) and seccomp/AppArmor profiles to limit system calls and prevent privilege escalation. Oracle's secure coding guidelines emphasize combining these with least-privilege principles to contain potential breaches.
To leverage built-in mitigations, migrate applications to Java 21 LTS (released September 2023) or later, which introduces configurable deserialization filters via ObjectInputFilter.Config.setSerialFilterFactory() and runtime monitoring events for serialized data, restricting unsafe gadgets by default and blocking known vulnerable patterns without custom code. This upgrade addresses legacy deserialization flaws pervasive in older JAR deployments, with later JDK versions enforcing module encapsulation that further limits reflective access to internal classes.
Tooling and Integration
Java Development Tools
The Java Development Kit (JDK) provides several core command-line utilities for creating, managing, and inspecting JAR files. Thejar command serves as the primary tool for building and extracting JAR archives, functioning as a general-purpose archiving and compression utility based on the ZIP and ZLIB formats. It supports operations such as creating new JAR files with the -c option, extracting contents using -x, and listing archive contents via -tf, enabling developers to package classes, resources, and manifests efficiently.[19]
For security, the jarsigner command handles digital signing and verification of JAR files, using private keys and certificates from a keystore to generate signatures stored in the META-INF directory, while also validating file integrity and certificate chains. Complementing this, the keytool utility manages keystores by generating key pairs, importing certificates, and listing entries, which is essential for preparing the cryptographic materials required for JAR signing.[46][47]
Integrated Development Environments (IDEs) based on the Java ecosystem incorporate wizards and build processes for JAR generation. In Eclipse, the JAR File Exporter allows selection of specific files, resources, and sources for packaging into a JAR, with options to include manifests and specify destinations. IntelliJ IDEA's Create JAR from Modules dialog facilitates exporting modules with dependencies, handling library extraction or direct inclusion to produce executable or library JARs. NetBeans IDE leverages Ant or Maven build scripts to automate JAR creation during project compilation, placing outputs in designated directories for deployment.[48][49][50]
At runtime, the [java](/page/Java) command's -jar option launches executable JAR files by loading the specified archive, identifying the main class from the manifest, and executing it within the Java Virtual Machine, streamlining application deployment. For inspection, the javap disassembler examines class files inside JARs, displaying public methods, fields, and bytecode when provided with a JAR path or class name.[51][52]
Diagnostic tools enhance JAR analysis, with jdeps, introduced in Java 8, performing dependency scans on JAR contents to reveal package-level or class-level relationships, including JDK internal usages, aiding in modularization and migration efforts. Introduced in Java 9, the jlink tool assembles custom runtime images by linking modules from JARs and other sources, optimizing for size and performance through compression and stripping options, which supports creating tailored JREs for JAR-based applications.[53][54]
Third-Party Support
Several third-party build tools provide support for creating and managing JAR files, extending beyond native Java tooling to integrate with broader development workflows. Apache Ant's<jar> task enables the packaging of files into JAR archives, allowing customization of manifests, filtering of contents, and specification of base directories for relative paths.[55] The Maven JAR plugin facilitates seamless JAR construction within the Maven build lifecycle, handling compilation, resource inclusion, and manifest generation as part of project phases like package and install.[21] Similarly, Gradle's Java plugin includes a dedicated JAR task that bundles compiled classes and resources, supporting configurable archive names and manifest attributes for multi-module builds.[56] For Scala projects, the sbt build tool offers packaging commands that produce JAR files containing Scala-compiled classes, with options to export jars instead of directories for distribution.[57]
Compatibility tools treat JAR files primarily as ZIP archives, enabling basic operations without full Java-specific features. Utilities like 7-Zip allow extraction, viewing, and compression of JAR contents, effectively handling them as standard ZIP files for file management tasks.[58] Android Studio, in building APK files—which are ZIP-based packages akin to JARs—incorporates JAR signing schemes via tools like apksigner, ensuring compatibility with Java archive structures during Android app development.[59]
Programmatic libraries extend JAR handling to non-Java environments. Apache Commons Compress, a Java library, provides APIs for reading, writing, and manipulating JAR archives through its ZIP support, while preserving interoperability with JAR-specific elements like manifests when possible.[60]
However, non-Java tools generally overlook JAR manifest semantics, such as the Main-Class attribute, treating files as generic ZIPs and potentially requiring manual intervention for executable functionality.[61]
Related Formats
Java-Specific Archives
In the Java ecosystem, the Web Application Archive (WAR) format extends the JAR structure to package web applications for deployment in Java EE (now Jakarta EE) environments. A WAR file is a ZIP-based archive, similar to a JAR, but it includes a mandatoryweb.xml deployment descriptor in the WEB-INF directory to configure servlets, filters, and other web components.[62] This format is specifically designed for Java EE web applications, enabling deployment to servlet containers like Apache Tomcat or full application servers.[63]
The Enterprise Archive (EAR) format builds upon JAR and WAR to encapsulate complete enterprise applications, bundling one or more WAR files, EJB JARs, and other modules within a single archive. Like JAR, an EAR is ZIP-based and contains an application.xml deployment descriptor in the META-INF directory to define modules, security roles, and resource references for Java EE deployments.[62] EARs facilitate modular organization in large-scale applications, allowing independent development and deployment of components across enterprise systems.[63]
For resource integration, the Resource Adapter Archive (RAR) format packages Java EE Connector Architecture (JCA) components, such as resource adapters for connecting enterprise information systems. A RAR file follows the ZIP structure of JARs and includes an ra.xml deployment descriptor in the META-INF directory to specify adapter configuration, connection factories, and security settings.[64] This format is tailored for JCA-compliant connectors, enabling standardized integration with external resources like databases or messaging systems.[62]
While JAR files primarily serve as containers for libraries, standalone applications, or executable Java code, WAR, EAR, and RAR formats incorporate additional deployment descriptors to support Java EE's web, enterprise, and connector-specific requirements. All these formats share the underlying ZIP compression and JAR manifest structure, but the specialized archives add hierarchical organization and metadata for application server deployment.[62]
Following the transition from Java EE to Jakarta EE in the late 2010s, these archive formats have persisted into the 2020s with updates to their XML deployment descriptors, including schema changes to reflect the namespace shift from javax.* to jakarta.* starting in Jakarta EE 9, with updates continuing through Jakarta EE 11, released in June 2025.[65] This evolution ensures compatibility with modern Jakarta EE platforms while maintaining the core ZIP-based packaging model.

