Of course! Let's dive deep into the MANIFEST.MF file in Java. It's a crucial but often misunderstood part of building Java applications, especially when they need to be packaged as JAR files.

What is MANIFEST.MF?
At its core, the MANIFEST.MF file is a special metadata file contained within a JAR (Java Archive) file. It's used to provide information about the JAR file and its contents to the Java Virtual Machine (JVM) and other tools.
Think of it as the "ID card" or "table of contents" for your JAR file. It contains key-value pairs that describe the archive's attributes.
Where is it Located?
Inside a JAR file, the MANIFEST.MF file is always located in a special path:
META-INF/MANIFEST.MF
The META-INF directory itself contains metadata for the archive, including:
MANIFEST.MF: The main manifest file.*.SF: Signature files for signed JARs.*.DSA: The digital signature block files.*.RSA: The digital signature block files.
The Structure of MANIFEST.MF
The file is simple and follows a specific format:
-
Key-Value Pairs: Each line contains a key and its value, separated by a colon () followed by a single space.
Manifest-Version: 1.0 Created-By: Apache Maven 3.8.1
-
Line Continuation: If a value is too long for one line, it must be continued on the next line. The continuation line must start with a space.
Main-Class: com.example.myapp.very.long.package.name. MainApplicationClass -
Sections: The manifest is divided into sections. The first section is the main attributes, which apply to the entire JAR. Subsequent sections, called named sections, apply to specific files within the JAR.
Manifest-Version: 1.0 Created-By: 11.0.12 (Oracle Corporation) Name: com/example/myapp/Main.class SHA-256-Digest: a1b2c3d4... (a hash of the file) Name: com/example/myapp/config.properties SHA-256-Digest: e5f6g7h8... (a hash of the file)
The Most Common Manifest Attributes
Here are the attributes you'll use most frequently:
Manifest-Version: 1.0
This is the only required attribute. It specifies the version of the manifest format. The only defined value is 0.
Main-Class: your.full.ClassName
This is the most important attribute for creating executable JARs. It tells the JVM which class contains the public static void main(String[] args) method to run when the JAR is executed with java -jar yourfile.jar.
Example:
Main-Class: com.mycompany.cli.MainApp
Class-Path: a.jar b.jar/ lib/ c.jar
This attribute is used to specify other JAR files or directories that the application depends on. The JVM will automatically add these locations to its classpath when the main JAR is run.
Important Notes on Class-Path:
- Paths are relative to the directory containing the main JAR file, not relative to the JAR file itself.
- Use spaces to separate entries. If a path contains spaces, it should be quoted (though this can be tricky and is often avoided).
- Forward slashes () are used as path separators, which works on all platforms.
Example:
If your my-app.jar is in /home/user/apps/, and your libraries are in /home/user/apps/lib/, your manifest would look like this:
Class-Path: lib/library1.jar lib/library2.jar
When you run java -jar /home/user/apps/my-app.jar from the /home/user/apps/ directory, the JVM will find the libraries.
Premain-Class: your.full.AgentClassName
This is used for Java agents. It specifies the class that contains the premain method, which is executed before the application's main method. This is the foundation for tools that instrument code at load time, like profilers and mock libraries (e.g., Mockito, Jacoco).
Example:
Premain-Class: com.mycompany.agent.InstrumentationAgent Can-Redefine-Classes: true Can-Retransform-Classes: true
How to Create and Include a MANIFEST.MF
You have several options, ranging from manual to highly automated.
Option 1: Manual Creation (The Hard Way)
-
Create the file: Create a text file named
MANIFEST.MFwith your desired content.Manifest-Version: 1.0 Main-Class: com.example.HelloWorld
-
Create the JAR: Use the
jarcommand-line tool to package your.classfiles and include the manifest.# Create a directory structure matching your package mkdir -p com/example # Compile your Java file javac com/example/HelloWorld.java # Create the JAR, including the manifest file # The 'm' flag specifies the manifest file jar cvfm my-app.jar MANIFEST.MF com/
c: create a new archivev: generate verbose outputf: specify the archive file namem: include the manifest information from the specified file
Option 2: Using an IDE (e.g., IntelliJ, Eclipse)
Modern IDEs make this very easy.
-
IntelliJ IDEA:
- Go to
File->Project Structure.... - Select
Artifactsfrom the left menu. - Click the button and choose
JAR->From modules with dependencies.... - In the dialog box, select your main module.
- Check the box for "Build on make".
- Go to the "Main Class" tab and select your main class.
- Go to the "Manifest" tab. The IDE will automatically generate the manifest with the correct
Main-Classentry.
- Go to
-
Eclipse:
- Right-click your project ->
Export.... - Choose
Java->Runnable JAR file. - Select your "Launch configuration" (which should point to your main class).
- Choose a "Library handling" option (e.g., "Package required libraries into generated JAR").
- Eclipse will automatically generate the manifest with the
Main-Classattribute.
- Right-click your project ->
Option 3: Using a Build Tool (The Recommended Way)
This is the most robust and common approach in professional development.
-
Maven: In your
pom.xml, you configure themaven-jar-plugin. TheaddClasspathandmainClassconfigurations are the most common.<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.2.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <mainClass>com.example.HelloWorld</mainClass> <!-- For multi-module projects, you might need this --> <classpathPrefix>lib/</classpathPrefix> </manifest> </archive> </configuration> </plugin> </plugins> </build>When you run
mvn package, Maven will automatically create aMETA-INF/MANIFEST.MFinside your target JAR with the correctMain-ClassandClass-Pathattributes. -
Gradle: In your
build.gradle(orbuild.gradle.kts), you configure thejartask.jar { manifest { attributes( 'Main-Class': 'com.example.HelloWorld', 'Class-Path': configurations.runtimeClasspath.files.collect { "lib/$it.name" }.join(' ') ) } }This configuration tells Gradle to build the manifest with the main class and a
Class-Pathentry for all runtime dependencies, placing them in alib/subdirectory.
Advanced Uses
- Java Agents: As mentioned,
Premain-Classand other attributes likeCan-Redefine-Classesare used for Java agents. - Services (Java SPI): The
META-INF/servicesdirectory can be used with theServiceLoaderto provide implementations for an interface without hardcoding dependencies. The manifest isn't directly involved here, but it's part of the same metadata ecosystem. - Signing JARs: When you sign a JAR, the manifest is updated with a digest (a hash) of each file. The signature files (
.SF,.DSA) then sign this manifest digest, ensuring the integrity of the entire archive. TheNameattribute in the manifest is crucial for this process.
Summary
| Attribute | Purpose | Common Use Case |
|---|---|---|
Manifest-Version |
Declares the manifest format version. | Required in every manifest. |
Main-Class |
Specifies the entry point for an executable JAR. | Creating java -jar runnable applications. |
Class-Path |
Lists external JARs/dirs for the classpath. | Managing application dependencies without complex build scripts. |
Premain-Class |
Specifies the entry point for a Java agent. | Instrumentation, profiling, testing (e.g., Mockito). |
While simple in concept, the MANIFEST.MF file is a powerful tool for controlling how your Java application is packaged and executed. Understanding it is key to moving from simple "hello world" projects to building real-world, distributable Java applications.
