4.8.7 | Paketversionierung |
Seit Version 1.2 wird die Versionierung von Paketen unterstützt. Voraussetzung ist, dass das Paket in einer JAR-Datei archiviert wird. Durch die Versionierung können verschiedene Entwicklungsstände eines Pakets unterschieden werden. Dies ist zum einen eine Erleichterung für den Entwickler, zum anderen erlaubt es den Programmen, die die Pakete benutzen, in Abhängigkeit von der Version Bug-Fixes zu aktivieren oder neue Klassen oder Methoden zu verwenden, deren Funktionalität zuvor »von Hand« erledigt werden musste. Diese beiden Beispiele deuten bereits ein wesentliches Merkmal der Paketversionierung in Java an: Bei der Versionierung wird zwischen der Schnittstelle eines Pakets und seiner Implementierung unterschieden, wobei folgende Grundsätze gelten:
- Die Schnittstelle muss immer abwärtskompatibel sein. Die Versionsnummer der Schnittstelle hat per Definition eine Ordnung, d. h., es gibt eine »ist kleiner«- und eine »ist größer«-Beziehung, mit der entschieden werden kann, welche Schnittstellenversion die neuere ist.
- Die Implementierung soll ein Verhalten aufweisen, das der Aufrufer erwartet. Im Gegensatz zu Schnittstellenversionen haben Versionen der Implementierungen keine Ordnung im Sinne von »neuer als«. Bei der Implementierung dient die Versionsnummer nur dazu, verschiedene Versionen unterscheiden zu können.
Da neue Implementierungen ja gerade erstellt werden, um ein unterschiedliches Verhalten zu realisieren, beispielsweise bei Bug-Fixes, sind sie gewissermaßen inkompatibel, und folglich macht es keinen Sinn, eine Ordnung auf der Implementierungsversion zu definieren.
Anhand der Version der Implementierung kann eine Klasse beispielsweise entscheiden, ob sie einen Workaround für einen Fehler eines benutzten Pakets aktivieren soll oder nicht. Für eine solche Entscheidung ist es nicht notwendig, dass die Versionen geordnet sind.
Die Versionsinformation muss vom Entwickler in einer so genannten Manifestdatei eingetragen werden, die zusammen mit den Klassendateien in das JAR-Archiv aufgenommen wird. JAR-Manifeste wurden im Rahmen der Java-Beans eingeführt. In einem Manifest kann neben der Versionsinformation auch spezifiziert werden, welche Klassen eines Archivs von einer Entwicklungsumgebung als Bean verwendet werden sollen und welche nicht. Paketversionierung kann aber unabhängig davon eingesetzt werden, ob es sich bei den archivierten Klassen um Beans handelt oder nicht.
Die Manifestdatei wird beim Erzeugen des Archivs mit jar durch eine spezielle Kommandozeilen-Option aufgenommen. Die Versionsinformation besteht aus folgenden Teilen:Um die Versionsinformation in das Manifest des JAR-Archivs aufzunehmen, muss sie zunächst in einer Datei eingetragen werden, die danach mit der Option -m beim jar-Aufruf angegeben wird.
- Titel, Version und Hersteller der Spezifikation, der das Paket entspricht. Die Versionsnummer muss wie sonst auch üblich aus durch Punkte getrennten ganzen Zahlen bestehen, z. B. 1.2.3. Buchstaben und andere Unicode-Zeichen sind nicht erlaubt, 1.2b4 wäre daher illegal. Die Schachtelungstiefe der Unterversionen ist prinzipiell beliebig.
- Titel, Version und Hersteller der Implementierung, die das Paket bereitstellt. Als Version kann eine beliebige Zeichenkette verwendet werden, die die vorliegende Implementierung eindeutig kennzeichnet.
Die Manifestdatei hat folgendes Format:Manifest-version: 1.0 Name: mydriver/ Specification-Title: "Java Database Connectivity" Specification-Version: "3.0" Specification-Vendor: "Sun Microsystems. Inc." Package-Title: "My JDBC Driver" Package-Version: "build35" Package-Vendor: "My Company"Im Eintrag Name: wird das Basisverzeichnis des Pakets angegeben, auf das sich die nachfolgenden Einträge beziehen. Die Specification- und Package-Einträge enthalten dann die eigentliche Versionsinformation.
In diesem Beispiel wird eine hypothetische Implementierung für die Java Database Connectivity (JDBC)-Schnittstelle bereitgestellt. JDBC ist eine von Sun spezifizierte Schnittstelle, für die Drittanbieter, z. B. Datenbankhersteller, Implementierungen anbieten. Diese Schnittstelle liegt gegenwärtig in der Version 3.0 vor. Der zweite Teil des Manifests enthält die Angaben über die vorliegende Implementierung dieser Schnittstelle: Name, Version und Hersteller.
Unter der Annahme, dass die Manifestdatei manifest.mf genannt wurde, kann das JAR-Archiv mit diesem Kommando erzeugt werden:jar cvfm mydriver.jar manifest.mf mydriver/
Um zur Laufzeit die Paketversionen ermitteln zu können, wurden verschiedene Neuerungen im Paket java.lang eingeführt. Die Versionsinformation im Manifest wird beim Laden des JAR-Archivs von der Virtual Machine ausgewertet. Danach wird ein Objekt der neuen Klasse java.lang.Package erzeugt. Package-Objekte gestatten den Zugriff auf die im vorhergehenden Abschnitt aufgezählten Informationen über das Paket. Weiterhin besitzt sie eine Methode isCompatibleWith(), mit der festgestellt werden kann, ob die Spezifikation eines Pakets kompatibel zu der eines anderen Pakets ist.
Die Klasse Class wurde durch die Methode getPackage() ergänzt, mit der das Package-Objekt zu einer gegebenen Klasse ermittelt werden kann.
Auch die Klasse ClassLoader wurde mit zwei Methoden zum Abrufen von Package-Objekten sowie mit der Methode definePackage() erweitert, mit der Package-Objekte erzeugt werden können.