Understanding the JAR Manifest File – 了解JAR描述文件

最后修改: 2019年 6月 19日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

A Java Archive (JAR) is described by its manifest file. This article explores its many capabilities, including adding attribution, making the JAR executable, and embedding versioning information.

一个Java归档文件(JAR)是由其清单文件描述的。本文探讨了它的许多功能,包括添加属性,使JAR可执行,以及嵌入版本信息。

Let’s begin, though, with a quick review of what a manifest file is.

不过,让我们先快速回顾一下什么是清单文件。

2. The Manifest File

2.清单文件

The manifest file is named MANIFEST.MF and is located under the META-INF directory in the JAR. It’s simply a list of key and value pairs, called headers or attributes, grouped into sections.

清单文件名为MANIFEST.MF,位于JAR的META-INF目录下。它只是一个键和值对的列表,称为headersattributes,分为几个部分。

These headers supply metadata that help us describe aspects of our JAR such as the versions of packages, what application class to execute, the classpath, signature material and much more.

这些头文件提供元数据,帮助我们描述JAR的各个方面,如包的版本、执行什么应用类、classpath、签名材料等等。

3. Adding a Manifest File

3.添加一个清单文件

3.1. The Default Manifest

3.1.默认清单

A manifest file is added automatically whenever we create a JAR.

每当我们创建一个JAR时,就会自动添加一个清单文件。

For example, if we build a JAR in OpenJDK 11:

例如,如果我们在OpenJDK 11中构建一个JAR。

jar cf MyJar.jar classes/

It produces a very simple manifest file:

它产生一个非常简单的清单文件。

Manifest-Version: 1.0
Created-By: 11.0.3 (AdoptOpenJDK)

3.2. A Custom Manifest

3.2.自定义清单

Or, we can specify our own manifest file.

或者,我们可以指定我们自己的清单文件。

For example, let’s say that we have a custom manifest file called manifest.txt:

例如,假设我们有一个名为manifest.txt的自定义清单文件。

Built-By: baeldung

We can include this file and jar will merge it with the default manifest file when we use the m option:

我们可以包括这个文件,当我们使用m 选项时,jar 与默认清单文件合并

jar cfm MyJar.jar manifest.txt classes/

Then, the resulting manifest file is:

然后,产生的清单文件是。

Manifest-Version: 1.0
Built-By: baeldung
Created-By: 11.0.3 (AdoptOpenJDK)

3.3. Maven

3.3.Maven

Now, the contents of the default manifest file change depending on which tools we use.

现在,默认清单文件的内容根据我们使用的工具而改变。

For example, Maven adds some extra headers:

例如,Maven增加了一些额外的头文件。

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven 3.3.9
Built-By: baeldung
Build-Jdk: 11.0.3

We can actually customize these headers in our pom.

实际上,我们可以在我们的pom中自定义这些头文件。

Say, for example, that we want to indicate who the JAR was created by and the package:

比如说,我们想表明JAR是由谁创建的,以及该包的情况。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.1.2</version>
    <configuration>
        <archive>
            <manifest>
                <packageName>com.baeldung.java</packageName>
            </manifest>
            <manifestEntries>
                <Created-By>baeldung</Created-By>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

This produces a manifest file with a custom package and created-by headers:

这将产生一个带有自定义packagecreated-by标题的清单文件。

Manifest-Version: 1.0
Build-Jdk-Spec: 11
Package: com.baeldung.java
Created-By: baeldung

Refer to the Maven JAR plugin documentation for a complete list of the options.

请参考Maven JAR插件文档,了解完整的选项列表。

4. Headers

4.页眉

A header must follow a certain format and be separated by a new line:

页眉必须遵循一定的格式,并由一个新行分隔。

key1: value1
Key2: value2

A valid header must have a space between the colon and the value. Another important point is there must be a new line at the end of the file. Otherwise, the last header is ignored.

一个有效的标题必须在冒号和数值之间有一个空格。另一个要点是文件的结尾必须有一个新行。否则,最后一个头会被忽略。

Let’s look at some of the standard headers from the specification and some common custom headers.

让我们看看规范中的一些标准头和一些常见的自定义头。

4.1. Main Headers

4.1.主要标题

Main headers typically provide general information:

主标题通常提供一般信息。

  • Manifest-Version: the version of the specification
  • Created-By: the tool version and vendor that created the manifest file
  • Multi-Release: if true, then this is a Multi-Release Jar
  • Built-By: this custom header gives the name of the user that created the manifest file

4.2. Entry Point and Classpath

4.2.入口点和类路径

If our JAR contains a runnable application then we can specify the entry point. Similarly, we can provide the classpath. By doing so, we avoid having to specify it when we want to run it.

如果我们的JAR包含一个可运行的应用程序,那么我们可以指定入口点。同样地,我们可以提供classpath。通过这样做,我们可以避免在我们想要运行它的时候指定它。

  • Main-Class: the package and name of the class with a main method (no .class extension)
  • Class-Path: a space separated list of relative paths to libraries or resources

For example, if our application entry point is in Application.class and it uses libraries and resources then we can add the needed headers:

例如,如果我们的应用程序入口点在Application.class中,并且它使用了库和资源,那么我们可以添加所需的头文件。

Main-Class: com.baeldung.Application
Class-Path: core.jar lib/ properties/

The classpath includes core.jar and all the files in the lib and properties directories. These assets are loaded relative to where the JAR is executed and not from within the JAR itself. In other words, they must exist outside the JAR.

classpath包括core.jar以及libproperties目录下的所有文件。这些资产是相对于JAR的执行位置加载的,而不是从JAR本身加载的。换句话说,它们必须存在于JAR之外。

4.3. Package Version and Sealing

4.3.包装版本和密封性

These standard headers describe the packages within the JAR.

这些标准头文件描述了JAR中的包。

  • Name: the package
  • Implementation-Build-Date: the build date for the implementation
  • Implementation-Title: the title of the implementation
  • Implementation-Vendor: the vendor for the implementation
  • Implementation-Version: the implementation version
  • Specification-Title: the title for the specification
  • Specification-Vendor: the vendor for the specification
  • Specification-Version: the specification version
  • Sealed: if true then all the classes for the package come from the same JAR (default is false)

For example, we find these manifest headers in the MySQL driver Connector/J JAR. They describe the version of the JDBC specification the JAR meets, as well as the version of the driver itself:

例如,我们在MySQL驱动程序Connector/J JAR中发现了这些清单头。它们描述了JAR所符合的JDBC规范的版本,以及驱动程序本身的版本。

Specification-Title: JDBC
Specification-Version: 4.2
Specification-Vendor: Oracle Corporation
Implementation-Title: MySQL Connector/J
Implementation-Version: 8.0.16
Implementation-Vendor: Oracle

4.4. Signed Jar

4.4.签名的罐子

We can digitally sign our JAR to add extra security and verification. While this process is outside the scope of this article, doing so adds standard headers showing each signed class and its encoded signature to the manifest file. Please see the JAR signing documentation for more details.

我们可以对我们的JAR进行数字签名,以增加额外的安全性和验证。虽然这个过程不在本文的讨论范围内,但这样做会在清单文件中添加显示每个签名类及其编码签名的标准头文件。请参阅JAR 签署文档以了解更多细节。

4.5. OSGI

4.5.OSGI

It’s common to also see the custom headers for OSGI bundles:

通常还可以看到OSGI捆绑包的自定义头文件:

  • Bundle-Name: title
  • Bundle-SymbolicName: a unique identifier
  • Bundle-Version: version
  • Import-Package: packages and versions the bundle depends on
  • Export-Package: bundle packages and versions available for use

See our Introduction to OSGI article to learn more about OSGI bundles.

请参阅我们的Introduction to OSGI文章以了解更多关于OSGI捆绑的信息。

5. Sections

5.节点

There are two types of sections in a manifest file, main and per-entry. Headers that appear in the main section apply to everything in the JAR.  Whereas headers that appear in the per-entry sections only apply to the named package or class.

在清单文件中,有两种类型的部分,即主部分和每个条目。出现在主部分的头信息适用于 JAR 中的所有内容。 而出现在每个条目部分的标题只适用于指定的包或类

In addition, a header appearing in a per-entry section overrides the same header in the main section. It is common for per-entry sections to contain information on package versions and sealing plus digital signing.

此外,出现在每个条目部分的标头会覆盖主条目部分的相同标头。每个条目部分通常包含关于软件包版本和密封以及数字签名的信息。

Let’s look at a simple example of a per-entry section:

让我们看看一个简单的例子,即每个条目的部分。

Implementation-Title: baeldung-examples 
Implementation-Version: 1.0.1
Implementation-Vendor: Baeldung
Sealed: true

Name: com/baeldung/utils/
Sealed: false

The main section at the top has sealed all packages within our JAR. However, the package com.baeldung.utils is unsealed by the per-entry section.

顶部的主部分已经密封了我们JAR中的所有包。然而,包com.baeldung.utils被每个条目部分解封。

6. Conclusion

6.结论

This article provides an overview of how to add a manifest file to a JAR, how to use sections and some common headers. The structure of the manifest file allows us to provide standard information, such as version information.

本文概述了如何向 JAR 添加清单文件、如何使用部分和一些常见的头文件。通过清单文件的结构,我们可以提供标准信息,如版本信息。

However, its flexibility allows us to define whatever information we find relevant to describe the content of our JARs.

然而,它的灵活性允许我们定义任何我们认为相关的信息来描述我们的JAR的内容。