杰瑞科技汇

java manifest.mf

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.

java manifest.mf-图1
(图片来源网络,侵删)

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:

  1. 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
  2. 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
  3. 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)

  1. Create the file: Create a text file named MANIFEST.MF with your desired content.

    Manifest-Version: 1.0
    Main-Class: com.example.HelloWorld
  2. Create the JAR: Use the jar command-line tool to package your .class files 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 archive
    • v: generate verbose output
    • f: specify the archive file name
    • m: 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:

    1. Go to File -> Project Structure....
    2. Select Artifacts from the left menu.
    3. Click the button and choose JAR -> From modules with dependencies....
    4. In the dialog box, select your main module.
    5. Check the box for "Build on make".
    6. Go to the "Main Class" tab and select your main class.
    7. Go to the "Manifest" tab. The IDE will automatically generate the manifest with the correct Main-Class entry.
  • Eclipse:

    1. Right-click your project -> Export....
    2. Choose Java -> Runnable JAR file.
    3. Select your "Launch configuration" (which should point to your main class).
    4. Choose a "Library handling" option (e.g., "Package required libraries into generated JAR").
    5. Eclipse will automatically generate the manifest with the Main-Class attribute.

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 the maven-jar-plugin. The addClasspath and mainClass configurations 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 a META-INF/MANIFEST.MF inside your target JAR with the correct Main-Class and Class-Path attributes.

  • Gradle: In your build.gradle (or build.gradle.kts), you configure the jar task.

    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-Path entry for all runtime dependencies, placing them in a lib/ subdirectory.


Advanced Uses

  • Java Agents: As mentioned, Premain-Class and other attributes like Can-Redefine-Classes are used for Java agents.
  • Services (Java SPI): The META-INF/services directory can be used with the ServiceLoader to 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. The Name attribute 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.

分享:
扫描分享到社交APP
上一篇
下一篇