Grundlegendes zur JAR-Manifestdatei

1. Einleitung

Ein Java-Archiv (JAR) wird durch seine Manifestdatei beschrieben. In diesem Artikel werden die zahlreichen Funktionen erläutert, darunter das Hinzufügen von Attributen, das Ausführen der ausführbaren JAR-Datei und das Einbetten von Versionsinformationen.

Beginnen wir jedoch mit einem kurzen Überblick darüber, was eine Manifestdatei ist.

2. Die Manifestdatei

Die Manifestdatei heißt MANIFEST.MF und befindet sich im Verzeichnis META-INF in der JAR. Es ist einfach eine Liste von Schlüssel- und Wertepaaren, die als Überschriften oder Attribute bezeichnet werden und in Abschnitte unterteilt sind.

Diese Header enthalten Metadaten, mit denen wir Aspekte unserer JAR beschreiben können, z. B. die Versionen von Paketen, die auszuführende Anwendungsklasse, den Klassenpfad, das Signaturmaterial und vieles mehr.

3. Hinzufügen einer Manifestdatei

3.1. Das Standardmanifest

Eine Manifestdatei wird automatisch hinzugefügt, wenn wir eine JAR erstellen.

Wenn wir beispielsweise eine JAR in OpenJDK 11 erstellen:

jar cf MyJar.jar classes/

Es wird eine sehr einfache Manifestdatei erstellt:

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

3.2. Ein benutzerdefiniertes Manifest

Oder wir können unsere eigene Manifestdatei angeben.

Angenommen, wir haben eine benutzerdefinierte Manifestdatei mit dem Namen manifest.txt :

Built-By: baeldung

Wir können diese Datei einschließen und jar wird sie mit der Standardmanifestdatei zusammenführen, wenn wir die Option m verwenden :

jar cfm MyJar.jar manifest.txt classes/

Die resultierende Manifestdatei lautet dann:

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

3.3. Maven

Der Inhalt der Standardmanifestdatei ändert sich nun je nachdem, welche Tools wir verwenden.

Zum Beispiel fügt Maven einige zusätzliche Header hinzu:

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

Wir können diese Header in unserem Pom tatsächlich anpassen.

Angenommen, wir möchten angeben, von wem die JAR erstellt wurde und welches Paket:

 org.apache.maven.plugins maven-jar-plugin 3.1.2    com.baeldung.java   baeldung    

Dadurch wird eine Manifestdatei mit einem benutzerdefinierten Paket und von Headern erstellten Dateien erstellt :

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

Eine vollständige Liste der Optionen finden Sie in der Dokumentation zum Maven JAR-Plugin.

4. Überschriften

Ein Header muss einem bestimmten Format folgen und durch eine neue Zeile getrennt sein:

key1: value1 Key2: value2

Ein gültiger Header muss ein Leerzeichen zwischen dem Doppelpunkt und dem Wert enthalten . Ein weiterer wichtiger Punkt ist, dass am Ende der Datei eine neue Zeile stehen muss . Andernfalls wird der letzte Header ignoriert.

Schauen wir uns einige der Standardheader aus der Spezifikation und einige gängige benutzerdefinierte Header an.

4.1. Hauptüberschriften

Hauptüberschriften enthalten normalerweise allgemeine Informationen:

  • Manifest-Version : Die Version der Spezifikation
  • Erstellt von : Die Toolversion und der Hersteller, die die Manifestdatei erstellt haben
  • Multi-Release : Wenn dies zutrifft , handelt es sich um ein Multi-Release-Glas
  • Built-By : Dieser benutzerdefinierte Header gibt den Namen des Benutzers an, der die Manifestdatei erstellt hat

4.2. Einstiegspunkt und Klassenpfad

Wenn unsere JAR eine ausführbare Anwendung enthält, können wir den Einstiegspunkt angeben. Ebenso können wir den Klassenpfad bereitstellen . Auf diese Weise müssen wir es nicht angeben, wenn wir es ausführen möchten.

  • Main-Klasse : das Paket und der Name der Klasse mit einer main - Methode (keine Erweiterung .class)
  • Klassenpfad : Eine durch Leerzeichen getrennte Liste relativer Pfade zu Bibliotheken oder Ressourcen

Wenn sich unser Anwendungseinstiegspunkt beispielsweise in Application.class befindet und Bibliotheken und Ressourcen verwendet, können wir die erforderlichen Header hinzufügen:

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

Der Klassenpfad enthält core.jar und alle Dateien in den Verzeichnissen lib und properties . Diese Assets werden relativ zu dem Ort geladen, an dem die JAR ausgeführt wird, und nicht innerhalb der JAR selbst . Mit anderen Worten, sie müssen außerhalb des JAR existieren.

4.3. Paketversion und Versiegelung

Diese Standardheader beschreiben die Pakete innerhalb der JAR.

  • Name : das Paket
  • 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:

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

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.

4.5. OSGI

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

  • 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.

5. Sections

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.

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.

6. Conclusion

Dieser Artikel bietet einen Überblick über das Hinzufügen einer Manifestdatei zu einer JAR, die Verwendung von Abschnitten und einige häufig verwendete Header. Die Struktur der Manifestdatei ermöglicht es uns, Standardinformationen wie Versionsinformationen bereitzustellen.

Aufgrund seiner Flexibilität können wir jedoch alle Informationen definieren, die für die Beschreibung des Inhalts unserer JARs relevant sind.