Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

Java ist auch eine Insel von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 5 (Tiger-Release)
Buch: Java ist auch eine Insel
gp Kapitel 25 Dienstprogramme für die Java-Umgebung
  gp 25.1 Die Werkzeuge im Überblick
  gp 25.2 Der Compiler javac
    gp 25.2.1 Der Java-Interpreter java
    gp 25.2.2 Der Unterschied zwischen java.exe und javaw.exe
  gp 25.3 Das Archivformat Jar
    gp 25.3.1 Das Dienstprogramm Jar benutzen
    gp 25.3.2 Das Manifest
    gp 25.3.3 Applikationen in Jar-Archiven starten
    gp 25.3.4 Applets in Jar-Archiven
    gp 25.3.5 Der Eintrag Class-Path in einer Manifest-Datei
  gp 25.4 Nativer Compiler JET
  gp 25.5 Einpacken von Java-Programmen in ein exe mit JSmooth
  gp 25.6 Decompiler
    gp 25.6.1 Jad, ein schneller Decompiler
    gp 25.6.2 SourceAgain
    gp 25.6.3 Decompilieren erschweren
  gp 25.7 Obfuscate Programm RetroGuard
  gp 25.8 Sourcecode Beautifier
  gp 25.9 Ant
    gp 25.9.1 Bezug und Installation von Ant
    gp 25.9.2 Properties
    gp 25.9.3 Externe und vordefinierte Properties
    gp 25.9.4 Weitere Leistungen


Galileo Computing

25.3 Das Archivformat Jadowntop

Sun Microsystems hat in der Version 1.1 ein Archivformat eingeführt, welches Zip ähnelt und durch das Dienstprogramm jar beim JDK unterstützt wird. Verbinden wir Java und Archiv, so ergibt sich schnell Suns Wortschöpfung JAR (Java-Archive). Zusätzlich zum Dienstprogramm gibt es auch eine API im Paket java.util.jar. Unter 1.2 hat das Jar-Dateiformat einige Erweiterungen erfahren.

Wie für ein Archivformat üblich, werden bei Jar mehrere Dateien zusammengepackt. »Gepackt« heißt aber nicht zwingend, dass die Dateien auch komprimiert werden. Jar-Dateien werden oft nicht komprimiert, sondern bündeln nur einfach die einzelnen Dateien. Ein Auspackprogramm wie Winzip kann jedoch auch Jar-Archive auspacken. Hier bleibt zu überlegen, ob ein Programm wie Winzip bei .jar geöffnet werden soll oder ob das Standardverhalten bei installiertem Jre beibehalten wird. Unter Windows ist mit der Dateiendung .jar das Programm Jre verbunden, welches die Hauptklasse des Archivs startet.

Dass ein Archiv gegenüber einzelnen Dateien Vorteile bringt, sehen wir etwa bei kleinen Applets mit zusätzlichen Ressourcen. Erinnern wir uns, dass der Applet-Klassenlader für jede zu übertragende Datei eine neue Verbindung aufbaut. Der Browser muss anstatt vieler kleiner Server-Verbindungen für jede einzelne Klassendatei und jede Ressource bei einem Archiv nur eine HTTP-Verbindung aufbauen. Auch wenn ein unkomprimiertes Archiv etwas größer ist als die vielen kleinen Dateien zusammen, ist die Übertragungszeit des Archivs kürzer, da jeder Verbindungsaufbau überproportional viel Zeit kostet. Da sich das Archiv darüber hinaus komprimieren lässt, sparen wir noch mehr Übertragungszeit und Bandbreite. Wir dürfen jedoch nicht vergessen, dass ein Archiv mitunter auch Nachteile mit sich bringen kann. Dann nämlich, wenn wir nur wenige Klassen des Archivs benötigen. Normalerweise lädt der Applet-Klassenlader die Klassen nur dann, wenn sie gebraucht werden. In einem Archiv sind aber alle Klassen enthalten, die während der gesamten Sitzung verwendet werden.

Microsoft vertraut bei seinem ActiveX-Controls vollständig auf Zertifikate. Es wird angenommen, dass kein Bösewicht ein Control anbietet, da dieser sich ja vorher ein Zertifikat geholt haben müsste, über das der Übeltäter verfolgt werden könnte. Haha! Leider ist in dieser Kette ein Denkfehler, denn Zertifikate kann sich jeder ausstellen lassen, auch unter dem Namen Micky Mouse.

Mit Bedacht angewendet, ist das Konzept jedoch gut zu verwenden. Sun hat daher das gleiche Konzept bei Jar-Archiven eingeführt. Sie lassen sich durch eine Signatur schützen. Eine Laufzeitumgebung kann nun den Java-Programmen anhand der Signatur Extrarechte einräumen, die ein normales Programm sonst nicht hätte. Dies ist bei Programmen aus dem Intranet interessant.

Einige Eigenschaften sind beim Jar-Archiv ab der Version 1.2 hinzugekommen. So etwa, dass Hersteller Informationen über Version und Kennung hinzufügen können und ebenso eine Versionskontrolle, dass nur Klassen eines Archivs verwendet werden, um innerhalb der gleichen Version zu bleiben. Ferner kam ein Archivformat hinzu, so dass Pakete zur Core-Plattform API hinzugenommen werden können. Ein Beispiel ist etwa die 3D- und Java-Mail-API. Eigene Pakete sehen also so aus, als gehörten sie zum Standard.


Galileo Computing

25.3.1 Das Dienstprogramm Jar benutzen  downtop

Jar besitzt verschiedene Optionen, um Archive zu erzeugen, sie auszupacken und anzusehen. Wenn wir Jar-Archive konstruiert haben, werden wir uns auch damit beschäftigen, wie sie aus Applets genutzt werden können. Das allgemeine Format für Jar ist:


$ jar Optionen Jar-Datei [Eingabedatei(en)]

Jar-Dateien anlegen

Die notwendige Option für das Anlegen eines neuen Archivs ist c (für engl. create). Da wir häufig die Ausgabe (das neue Archiv) in einer Datei haben wollen, geben wir zusätzlich noch f (für engl. file) an. Somit können wir schon unser erstes Archiv erstellen. Nehmen wir dazu an, es gibt ein Verzeichnis images für Bilder und die Klasse Slider.class. Dann packt folgende Zeile die Klasse und alle Bilder in das Archiv Slider.jar:


$ jar cvf Slider.jar Slider.class images

Während des Komprimierens geht Jar alle angegebenen Verzeichnisse und Unterverzeichnisse durch und gibt, da zusätzlich zu cf der Schalter v gesetzt ist, auf dem Bildschirm die Dateien mit einem Kompressionsfaktor an.


adding: Slider.class (in=2790) (out=1506) (deflated 46  %)
adding: images/ (in=0) (out=0) (stored 0  %)
adding: images/darkwing.gif (in=1065) (out=801) (deflated 24  %)
adding: images/volti.gif (in=173) (out=154) (deflated 10  %)
adding: images/superschurke.gif (in=1076)(out=926)(deflated 13  %)
adding: images/aqua.gif (in=884) (out=568) (deflated 35  %)

Anstatt der Dateinamen können wir auch * oder andere Wildcards angeben. Diese Expansionsfähigkeit ist ohnehin Aufgabe der Shell.

Möchten wir die Dateien nicht komprimiert haben, sollten wir den Schalter 0 angeben.

Jar behält bei den zusammengefassten Dateien die Verzeichnisstruktur. Wir sehen in der Ausgabe, dass für images ein eigenes Verzeichnis im Archiv erstellt wird und die Bilder dort hineinkopiert werden. Seit dem Java-SDK 1.2 bildet der Schalter C (genau wie -C beim Kompressionsprogramm Gzip) diese hierarchische Struktur flach ohne Verzeichnisstruktur ab. Wenn wir mehrere Verzeichnisse zusammenpacken, lässt sich für jedes Verzeichnis bestimmen, ob die Struktur erhalten bleiben soll oder nicht. Nehmen wir zu unserem Sliders-Archiv noch ein weiteres Verzeichnis mit Sound-Dateien hinzu und beobachten die Ausgabe bei


$ jar cfv0 Slider.jar Slider.class images -C sounds

Zwei Sachen sind neu. Zum einen komprimieren wir nicht mehr (Schalter 0 ist gesetzt), und wir haben mit C erreicht, dass Jar in das sound-Verzeichnis geht und dort alle Sound-Dateien in das Basisverzeichnis setzt.

Einer angelegten Archiv-Datei lassen sich später mit u (für engl. update) noch Dateien hinzufügen. Nehmen wir an, es kommt noch eine Bilddatei hinzu, so schreiben wir:


$ jar vuf Slider.jar images/buchsbaum.gif

Jar-Dateien betrachten

Um die zusammengepackten Dateien anzuzeigen, nutzen wir die Option tf.


$ jar tf Slider.jar
META-INF/MANIFEST.MF
Slider.class
images/volti.gif

Zusätzlich zu unseren Dateien sehen wir noch eine von Jar eigenständig hinzugefügte Manifest-Datei, die wir etwas später besprechen wollen.

Fehlt die Endung oder wird ein falscher Dateiname angegeben, so folgt eine etwas ungewöhnliche Fehlermeldung: java.io.FileNotFoundException: Dateiname und dann ein Stacktrace. Dies wirkt etwas unprofessionell.

Zum Anzeigen der Archive muss auf jeden Fall der Schalter t (für engl. table of contents) benutzt werden. Wir geben f nur deshalb an, weil wir den Dateinamen auf der Kommandozeile eintragen und nicht von der Standardeingabe etwa über eine Pipe lesen. Zusätzlich dazu gibt uns der Schalter v (für engl. verbose) noch den Zeitpunkt der letzten Änderung und die Dateigröße aus.


291 Fri Dec 17 14:51:08 GMT 1999 META-INF/MANIFEST.MF
  2790 Thu Dec 16 14:54:06 GMT 1999 Slider.class
   173 Mon Oct 14 00:38:00 GMT 1996 images/volti.gif

Dateien aus dem Archiv extrahieren

Der wichtigste Schalter beim Entpacken ist x (für engl. extract). Zusätzlich gilt für den Schalter f (file) das Gleiche wie beim Anzeigen: ohne den Schalter wird die Archiv-Datei in der Standardeingabe erwartet. Als Parameter ist zusätzlich das Archiv erforderlich. Sind optional Dateien oder Verzeichnisse angegeben, werden nur diese ausgepackt. Verzeichnisse werden automatisch erzeugt. Hier ist Vorsicht geboten, denn Jar überschreibt alle Dateien, die schon mit dem gleichen Namen auf dem Datenträger existieren. Das Archiv bleibt nach dem Auspacken erhalten. Wir wollen jetzt nur die Grafiken aus unserem Archiv Slider.jar auspacken. Dazu schreiben wir:


$ jar vxf Slider.jar images\*
 extracted: images\volti.gif

Die Option v haben wir eingesetzt, damit wir sehen, was genau entpackt wird. Sonst erfolgt keine Ausgabe auf der Konsole.


Galileo Computing

25.3.2 Das Manifest  downtop

Ohne dass die Ausgabe es zeigt, fügt Jar beim Erzeugen eines Archivs automatisch eine Manifest-Datei mit dem Namen META-INF/MANIFEST.MF ein. Ein Manifest enthält für ein Archiv wichtige Zusatzinformationen, wie die Signatur, die für jede Datei aufgeführt ist. Sehen wir uns einmal die Manifest-Datei an, die sich für


$ jar cfv Slider.jar Slider.class images/volti.gif

ergibt. Die Einträge im Manifest erinnern an eine Property-Datei, denn auch hier gibt es immer Schlüssel und Werte, die durch einen Doppelpunkt getrennt sind. Da sich das Manifest zwischen 1.1 und 1.2 geändert hat, listen wir beide Dateien auf. Für das JDK 1.1 sieht das Manifest dann wie folgt aus:


Manifest-Version: 1.0

Name: Slider.class
Digest-Algorithms: SHA MD5
SHA-Digest: /RD8BF1mwd3bYXcaYYkqLjCkYdw=
MD5-Digest: WcnCNJbo08PH/ATqMHqZDw==

Name: images/volti.gif
Digest-Algorithms: SHA MD5
SHA-Digest: 9zeehlViDy0fpfvOKkPECiMYvH0=
MD5-Digest: qv913KlZFi5tdPr2BjatIg==

Galileo Computing

25.3.3 Applikationen in Jar-Archiven starten  downtop

Dass die Dateien zusammen in einem Archiv sind, hat für Entwickler den Vorteil, dass sie dem Kunden nur eine einzige Datei ausliefern müssen und nicht ein ganzes Bündel von Klassen- und Ressourcen-Dateien. Praktischerweise ist unter Windows mit der Endung .jar gleich die JRE (Java Runtime Evironment) verbunden, so dass Programme direkt gestartet werden können. Eine kleine Veränderung der Manifest-Datei ist jedoch dafür nötig, denn damit der Interpreter weiß, wo er seine Arbeit beginnen kann, sieht er in die Manifest-Datei und sucht nach dem Schlüssel Main-Class:


Main-Class: Klassenname_vom_main

Dies ist sehr elegant für den Benutzer eines Archivs, denn nun ist der Hersteller für den Eintrag des Einstiegspunkts im Manifest verantwortlich.

Manifest-Dateien mit Main-Class Einträgen erstellen

Damit dem Jar-Archiv die Main-Klasse mitgeteilt werden kann, lässt sich das m-Flag (für engl. merge) beim Dienstprogramm Jar nutzen, um Einträge zum Manifest hinzuzufügen. Bevor ein Archiv erzeugt wird, erstellen wir eine beliebige Textdatei, die wir hier MainfestMain.txt nennen wollen, mit dem Eintrag Main-Class. Wenn unser Slider-Programm etwa die Hauptklasse Main.class besitzt, schreiben wir

Listing 25.1   MainfestMain.txt


Main-Class: Main

Nun lässt sich die Datei MainfestMain.txt mit der Manifest-Datei zusammenbinden und anschließend benutzen:


$ jar cmf MainfestMain.txt Slider.jar Main.class
$ java -jar Slider.jar
$ java -jar Slider.jar Main

Von der Kommandozeile starten

Wenn der Interpreter java von der Kommandozeile gestartet wird, gibt die Option -jar das Archiv an und der Interpreter sucht im nach dem Startprogramm.


$ java -jar JarDatei.jar

Galileo Computing

25.3.4 Applets in Jar-Archiven  downtop

Jar-Archive sind für Applets ein Vorteil, da alle Dateien zusammen komprimiert übertragen werden und der Klassenlader nicht immer einzeln Klasse für Klasse beziehen muss. Im Applet-Tag werden zusätzliche Archive im Attribut archive aufgeführt:


<applet
  code=Main.class archive="Slider.jar"
  width=320 height=200>
</applet>

Wie bei Applets erwarten wir hier das Archiv zusammen mit der Klasse und der HTML-Datei in einem gemeinsamen Verzeichnis. Befindet sich das Jar-Archiv in einem Unterverzeichnis applets, so schreiben wir stattdessen:


<applet
  code=Main.class archive="applets/Slider.jar"
  width=320 height=200>
</applet>

Galileo Computing

25.3.5 Der Eintrag Class-Path in einer Manifest-Datei  toptop

Wenn ein Java-Archiv zusammengebunden wird, dann können wir dort beliebige Ressourcen platzieren. Diese können dann mit getResourceAsStream() gefunden werden. Doch stellen wir uns folgendes Archiv mit den drei Einträgen vor:


images/bild.gif
abc.jar
Bauchnabel.class

Wenn alle drei Dateien zu einem Archiv neu.jar zusammengebunden sind, kann der Klassenlader aus dem Archiv direkt Bauchnabel.class lesen und getResourceXXX() auch bild.gif – das Bild allerdings nur mit der absoluten Angabe images/bild.gif. Das innere Jar-Achiv wird vielleicht auch Klassen oder Ressourcen definieren, doch die sind erst einmal für den Klassenlader nicht zugänglich. Das wäre allerdings sinnvoll, denn es ist durchaus üblich, die gesamte Applikation mit den eigenen Klassen zusammen mit den nötigen Klassen in ein neues Archiv zu packen. Dann muss der Klassenlader allerdings auch die Klassen und Ressource in die inneren Jar-Archiven mitnutzen. Damit das funktioniert, muss in dem großen Jar-Archiv im Manifest eine Eintrag gesetzt sein: Class-Path. Dieser Kopf enthält eine Liste mit URLs, die Ressourcen angeben, die im Klassenpfad mit eingebunden werden.


Beispiel   Erlaube dem Klassenlader direkt auf Ressourcen in abc.jar und im Unterverzeichnis von images zuzugreifen.

Class-Path: abc.jar images/
Diese Angabe muss in der Manifest-Datei für das Java-Archiv eingebaut werden. Es darf durchaus mehrere Class-Path Zeilen geben. Auch im inneren Archiv abc.jar kann durchaus wieder ein Class-Path Eintrag enthalten sein, so dass eine beliebige Tiefe möglich ist.






1   Obwohl dieser schon vergeben ist, doch vielleicht ist Darkwin Duck ja noch frei.





Copyright © Galileo Press GmbH 2004
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de