Galileo Computing <openbook>
Galileo Computing - Programming the Net
Galileo Computing - Programming the Net


Java ist auch eine Insel von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 1.4
Buch: Java ist auch eine Insel - Zum Katalog
gp Kapitel 26 Dienstprogramme für die Java-Umgebung
  gp 26.1 Die Werkzeuge im Überblick
  gp 26.2 Der Compiler javac
    gp 26.2.1 Der Java-Interpreter java
  gp 26.3 Das Archivformat Jar
    gp 26.3.1 Das Dienstprogramm Jar benutzen
    gp 26.3.2 Das Manifest
    gp 26.3.3 Jar-Archive für Applets und Applikation
  gp 26.4 Mit JavaDoc und Doclets dokumentieren
    gp 26.4.1 Mit JavaDoc Dokumentationen erstellen
    gp 26.4.2 Wie JavaDoc benutzt wird
    gp 26.4.3 Dokumentation erstellen
    gp 26.4.4 JavaDoc und Doclets
    gp 26.4.5 Doclets programmieren
    gp 26.4.6 Das Standard-Doclet
  gp 26.5 Dienstprogramme zur Signierung von Applets
    gp 26.5.1 keytool
    gp 26.5.2 jarsigner
    gp 26.5.3 policytool
  gp 26.6 Konverter von Java nach C
    gp 26.6.1 Toba
    gp 26.6.2 Arbeitsweise von Toba
    gp 26.6.3 Abstriche des Konverters
  gp 26.7 Konverter von Java Byte Code in ein Windows-Exe mit JET
  gp 26.8 Manteln von Javaklassen in ein Windows-Exe mit JToExe
  gp 26.9 Decompiler
    gp 26.9.1 Jad, ein schneller Decompiler
    gp 26.9.2 SourceAgain
    gp 26.9.3 Decompilieren erschweren
  gp 26.10 Obfuscate Programm RetroGuard
  gp 26.11 Source-Code Beautifier

Kapitel 26 Dienstprogramme für die Java-Umgebung

Erfolg sollte stets nur die Folge,
nie das Ziel des Handelns sein.
– Gustave Flaubert


Galileo Computing

26.1 Die Werkzeuge im Überblick  downtop

In diesem Kapitel werden unter anderem die wichtigsten Programme des Java Development Kit vorgestellt. Da die Programme kommandozeilenorientiert arbeiten, werden sie zusammen mit ihrer Aufrufsyntax vorgestellt. Es handelt sich dabei um folgende Tools:

gp  Der Java-Compiler »javac« zum Übersetzen von .java in .class-Dateien
gp  Der Java-Interpreter »java« zum Ausführen der Java-Applikationen
gp  Der Applet-Viewer »appletviewer« zum Ausführen von Java-Applets in einer HTML-Datei
gp  Debuggen eines Programms mit dem Debugger »jdb«
gp  Erzeugen von Dokumentationen mit »javadoc«
gp  Das Archivierungswerkzeug »jar«, um Dateien in einem Archiv zusammenzufassen
gp  Programme zum Einstellen der Sicherheitseigenschaften über »keytool«, »jarsigner« und »policytool«

Es werden die Optionen der Version 1.4 aufgezeigt.


Galileo Computing

26.2 Der Compiler javac  downtop

javac übersetzt den Quellcode einer Datei in Java-Bytecode. Jede Klasse, die innerhalb einer Datei definiert wurde, wird zu einer Klassendatei umgewandelt. Ergibt es sich, dass zu einer Klasse (nennen wir sie A) eine Abhängigkeit zu einer anderen Klasse (nennen wir sie B) besteht, wenn zum Beispiel A von B erbt, und liegt B nicht als Bytecode-Datei vor, dann wird B automatisch mitcompiliert. Der Compiler überwacht dabei automatisch die Abhängigkeiten zwischen den Quelldateien. Der allgemeine Aufruf ist:

javac [ Optionen ] Dateiname(n).java
Tabelle 26.1   Optionen des Compilers javac
Option Bedeutung
-classpath Path Eine Liste von Pfaden, durch die der Compiler die Klassendateien finden kann. Diese Option überschreibt die unter Umständen gesetzte Umgebungsvariable CLASSPATH und ergänzt sie nicht. Es können mehrere Verzeichnisse durch Semikolon (Windows) oder Doppelpunkt (Unix) getrennt werden.
-d Verzeichnis Gibt an, wo die übersetzten .class-Dateien gespeichert werden. Ohne Angabe werden die Dateien im Verzeichnis der Quelldateien abgelegt.
-deprecation Als deprecated, veraltetet, markierte Methoden (JavaDoc-Comment @deprecated) werden angezeigt.
-g Erzeugt Debug-Informationen. Die Option muss gesetzt sein, damit der Debugger verwendet werden kann.
-nowarn Deaktiviert die Ausgabe von Warnungen. Es werden noch Fehler (Errors) angezeigt.
-sourcepath Quellpfad Ähnlich wie -classpath, nur wird in sourcepath nach den Quelldateien gesucht.
-verbose Ausgabe von Meldungen über geladene Quell- und Klassendateien während der Übersetzung.


Galileo Computing

26.2.1 Der Java-Interpreter java  downtop

Der Java-Interpreter führt den Java-Bytecode in der Laufzeitumgebung aus. Dazu sucht der Interpreter in der als Parameter übergebenen Klassendatei nach der speziellen main()-Methode. Der allgemeine Aufruf ist:

java [ Optionen ] Klassenname [ 
Argumente ]

Ist die Klasse in einem Paket definiert, muss der Name der Klasse voll qualifiziert sein. Das heißt, wenn etwa die Klasse Haupt im Paket com.java-tutor, also im Unterverzeichnis com/java-tutor, angesiedelt ist, dann muss als Klassenname com.java-tutor.Haupt angegeben werden. Die benötigten Klassen müssen die Laufzeitumgebung finden könnten. Der Interpreter wertet jedoch wie der Compiler die Umgebungsvariable CLASSPATH aus und lässt sich alternativ den Klassenpfad durch die Option -classpath angeben.

Die Argumente sind optional und werden beim Aufruf an die Klasse übergeben.

Tabelle 26.2   Optionen des Interpreters java
Option Bedeutung
-client Wählt die Java HotSpot Client VM, Standard
-server Wählt die Java HotSpot Server VM
-cp, -classpath Path Eine Liste von Pfaden, wo der Compiler die Klassendateien finden kann. Diese Option überschreibt die unter Umständen gesetzte Umgebungsvariable CLASSPATH und ergänzt sie nicht. Es können mehrere Verzeichnisse durch Semikolon (Windows) oder Doppelpunkt (Unix) getrennt werden.
-D Ressource = Wert Setzt den Wert einer Ressource, etwa java -Djdbc.drivers=sun.jdbc.odbc.JdbcOdbcDriver XY
-help oder -? Listet alle vorhandenen Optionen auf
-jar Startet Klasse aus dem Jar-Archiv, falls sie in der Manifest-Datei genannt ist. Die Haupt-Klasse lässt sich aber immer noch angeben.

-verbose

Informationen über die Laufzeitumgebung -verbose:class gibt Information über geladene Klassen -verbose:gc informiert über GC -verbose:jni informiert über native Aufrufe
-version Zeigt die aktuelle Version an
-X Zeigt nicht standardisierte Optionen an
-Xdebug Startet mit Debugger
-Xincgc Schaltet die inkrementelle GC ein
-Xms x Anfangsgröße des Speicherbereichs für die Allokation von Objekten (x MB), voreingestellt sind 2 MB

-Xmx x

Maximal verfügbarer Speicherbereichs für die Allokation von Objekten. Voreingestellt sind 64 MB. x beschreibt als einfache Zahl die Bytes oder Kilobytes mit einem angefügtem k oder Megabyte (angefügtes m).

-Xnoclassgc

Schaltet die GC für geladene aber nicht mehr benötigte Klassen aus

-Xprof

Der Interpreter schreibt Profiling-Informationen in der Datei java.prof

-Xrs

Reduziert intern die Verwendung von Unix-Signalen durch die Laufzeitumgebung. Das ergibt gegebenenfalls eine schlechtere Performance aber bessere Kompatibilität mit div. Unix/Solaris-Versionen.


Galileo Computing

26.3 Das Archivformat Jar  downtop

Sun Microsystems hat in der Version 1.1 ein Archivformat eingeführt, welches durch ein Dienstprogramm Jar beim JDK unterstützt wird. Verbinden wir Java und Archiv, so ergibt sich schnell Suns Wortschöpfung JAR (Java-Archive). Es ist selbst in Java implementiert und daher sehr portabel. Zusätzlich zum Dienstprogramm gibt es auch eine API im Paket java.util.jar. Unter 1.2 hat das Jar-Dateiformat ein paar 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 das Archiv etwas größer ist, ist die Zeit für die Übertragung des Archivs günstiger, als die vielen kleinen Dateien, 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 brauchen. 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 extra Rechte 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. Ebenso eine Versionskontrolle, dass nur Klassen eines Archivs verwendet werden, um innerhalb der gleichen Version zu bleiben. Ferner ein Archivformat, sodass 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

26.3.1 Das Dienstprogramm Jar benutzen  downtop

Jar besitzt verschiedene Optionen, um Archive zu erzeugen, sie auszupacken und anzuschauen. 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 ist c (für engl. create) für das Anlegen eines neuen Archivs. 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 sowieso Aufgabe der Shell.

Möchten wir die Dateien nicht komprimiert haben, so 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 erstellt und die Bilder dort hinein kopiert werden. Seit den JDK 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 Bild-Datei 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 Archivdatei 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 einmal 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

26.3.2 Das Manifest  downtop

Ohne das 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. Schauen 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 einmal 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

26.3.3 Jar-Archive für Applets und Applikation  downtop

Wir haben gesehen, dass Jar-Archive für Applets in der Regel ein Vorteil sind, da gleich alle Dateien zusammen übertragen werden und der Klassenlader nicht immer Netzwerkverbindungen aufbauen muss. 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. Zudem sind Bibliotheken eleganter getrennt. Unter Windows ist mit der Endung jar gleich die JRE (Java Runtime Evironment) verbunden, sodass Programme direkt gestartet werden können. Ein schöner Vorteil, denn vorher war das Ausführen nach einem Doppelklick schon etwas umständlicher.

Applikationen in Jar-Archiven

Bei Applikationen müssen wir zwischen Jar-Archiven für die Versionen 1.1 und 1.2 unterscheiden. Unter Java 1.1 müssen wir Java Runtime Environment mit dem Schalter -cp nutzen. Als Parameter ist zusätzlich zum Archivnamen auch der Name der Hauptdatei mit der statischen main()-Methode anzugeben.

$ jre -cp JarDatei.jar MainKlasse 
   // JDK 1.1

Ab Java 1.2 lässt sich der normale Interpreter java mit der Option -jar verwenden. (Dieser wurde erst ab 1.2 eingeführt.)

$ java -jar JarDatei.jar       
      // >= JDK 1.2

Wenn wir uns unter 1.1 befinden haben wir bei einem fremden Programm das Problem, dass wir nicht unbedingt wissen, wie die Main-Klasse heißt. Das ist für den Benutzer auch nicht nötig und erschwert das Benutzen des Jar-Archive. Doch irgendwo muss auch unter 1.2 die Main-Klasse stecken. Damit der Interpreter weiss, wo er seine Arbeit beginnen kann, schaut er ins Manifest und sucht nach dem Schlüssel Main-Class:

Main-Class: Klassenname_vom_main

Dies ist sehr elegant für den Benutzer, denn nun ist der Hersteller für den richtigen Einstiegspunkt verantwortlich. Aber dann haben wir ja das Problem!

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 einmal MainfestMain.txt nennen wollen, mit dem Eintrag Main-Class. Wenn unser Slider-Programm etwa die Hauptklasse Main.class besitzt, schreiben wir

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

Applets in Jar-Archiven

Ebenso wie eine normale Klasse in der HTML-Datei innerhalb eines APPLET-Tags gesetzt wird, erscheint zusätzlich auch die Jar-Datei:

<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 Verzeichnis. Ist etwa das Jar-Archiv in einem speziellen Unterverzeichnis applets, so schreiben wir statt dessen:

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

Galileo Computing

26.4 Mit JavaDoc und Doclets dokumentieren  downtop

Dokumentation von Softwaresystemen ist ein wichtiger, aber oft vernachlässigter Teil der Softwareentwicklung. Im Entwicklungsprozess müssen die Entwickler Zeit in Beschreibungen der einzelnen Komponenten stecken, besonders dann, wenn weitere Entwickler diese Komponenten wieder verwerten. Diese Wiederverwertung wird besonders bei der objektorientierten Programmierung angestrebt. Deshalb müssen die Schnittstellen sorgfältig beschrieben werden. Wichtige Beschreibungen sind die Art und die Anzahl der Parameter, die Wirkung der Funktionen und das Laufzeitverhalten. Da das Erstellen einer externen Dokumentation – also eine Beschreibung außerhalb der Quellcodedatei – fehlerträchtig und deshalb nicht gerade motivierend für die Beschreibung ist, werden spezielle Anweisungen in den Java-Quelltext eingeführt. Ein spezielles Programm generiert aus den Formatierungsanweisungen eine Textdatei mit den gewünschten Informationen .


Galileo Computing

26.4.1 Mit JavaDoc Dokumentationen erstellen  downtop

JavaDoc geht durch den Quelltext und parst die Deklarationen und zieht die Dokumentation heraus. Daraus generiert das Tool eine Beschreibung, die in der Regel als HTML-Seite zu uns kommt. Die Dokumentation beschreibt die Klassen (auch innere), die Vererbung, die Methoden und Felder, Interfaces und Konstruktoren.

Aus den Beschreibungen im Java-Quelltext werden folgende Informationen zusammengetragen:

gp  Kopf
gp  Diagramm der Klassenhierarchie
gp  Klassenbeschreibung
gp  Index der Public-Variablen
gp  Index der Public-Methoden
gp  Index der Konstruktoren
gp  Beschreibung der Public-Variablen
gp  Beschreibung der Public-Konstruktoren
gp  Beschreibung der Public-Methoden

Galileo Computing

26.4.2 Wie JavaDoc benutzt wird  downtop

In einer besonders ausgezeichneten Kommentarumgebung werden die beschreibenden Anweisungen Dokumentationskommentare (»Doc Comments«) eingesetzt. Die Kommentarumgebung ähnelt dem Blockkommentar.

Beispiel Ein Dokumentationskommentar

/**
* Socken sind spezielle Kleidungsstücke.
*/
public class Socke extends Kleidung
{
}

Da ein Dokumentationskommentar mit /** beginnt, ist es für den Compiler ein normaler Block-Kommentar. Die Kommentare werden oft optisch aufgewertet, in dem am Anfang ein Sternchen steht. Dieses wird von JavaDoc ignoriert.

Hinweis Die Dokumentationskommentare sind so aufbaut, dass der erste Satz in der Auflistung der Methoden und Attribute erscheint und der Rest in der Detail-Ansicht.

/**
* Das ist ein kurzer Satz.
* Das ist die ausführliche Beschreibung.
* Die Ausführliche Beschreibung erscheint
* später im Abschnitt "Method Detail".
* Der kurze Satz erscheint im Abschnitt "Method Summary".
*/
public void foo() { }

Dokumentationskommentare

Tabelle 26.3   Die wichtigsten Dokumentationskommentare im Überblick
Kommentar Beschreibung
@see Klassenname Verweis auf eine andere Klasse
@see Klassenname oder Methodenname Verweis auf eine andere Methode
@see Ausgeschriebener Klassenname Verweis auf voll qualifizierte Klasse
@see Ausgeschriebener Klassenname oder Methodenname Verweis auf voll qualifizierte Methode
@version Versionstext Version
@author Autor Schöpfer
@return Rückgabetext Rückgabewert
@param Parametername oder Parametertext Beschreibung der Paramter
@exception Exception-Klassenname oder Exceptiontext Ausnahmen, die ausgelöst werden können
@throws Exception-Klassenname oder
Exceptiontext
Synonym zu oben
{@link Verweis } Einen eingebauten Verweis im Text Parameter sind wie bei @see.

Beispiele Eine externe Zusatzquelle angeben:
@see <a href="spec.html#section">Java 
Spec</a>.

Verweis auf eine Funktion, die mit der beschriebenen Funktion verwandt ist:

/**
* @see String#equals(Object) equals */

Dokumentiere eine Variable. Gebe einen Verweis auf die Methode an:

/**
* The X-coordinate of the component.
*
* @see #getLocation()
*/
int x = 1263732;

Eine veraltete Methode, die auf eine Alternative zeigt:

/**
* @deprecated As of JDK 1.1,
* replaced by {@link #setBounds(int,int,int,int)}
*/

HTML-Tags in Dokumentationskommentaren

In den Kommentaren können HTML-Tags verwendet werden – beispielsweise <B>..</B> und <I>..</I> –, um Textattribute zu setzen. Sie werden direkt in die Dokumentation übernommen, müssen also korrekt geschachtelt sein, damit die Ausgabe nicht falsch dargestellt wird. Die Überschriften-Tags <H1>..</H1> und <H2>..</H2> sollten jedoch nicht verwendet werden. JavaDoc verwendet sie zur Gliederung der Ausgabe und weist ihnen Formatvorlagen zu.


Galileo Computing

26.4.3 Dokumentation erstellen  downtop

Um eine Dokumentation zu erzeugen, wird dem Konsolen-Programm javadoc als Parameter ein Dateinamen der zu kommentierenden Klasse übergeben; aus kompilierten Dateien können natürlich keine Beschreibungsdateien erstellt werden.

Beispiel Erstelle aus der Socken- und Kleidung-Klasse eine Dokumentation

Listing 26.1   Kleidung.java
/**
* Kleidung bildet die Oberklasse für alle Kleidungs-Objekte.
*/

import java.io.*;

public abstract class Kleidung implements Serializable
{
/**
* Jede Kleidung hat eine Farbe.
*/
protected String farbe;

/**
* Erzeugt neues Kleidungs-Objekt.
*/
protected Kleidung()
{
}

/**
* Erzeugt neues KleidungsObjekt,
* welches mit einer Farbe initialisiert wird.
*/
protected Kleidung( String farbe )
{
this.farbe = farbe;
}

/**
* Jede Kleidung hat einen Namen.
* Wird von Unterklassen überschrieben.
*/
abstract String getName();
}
Listing 26.2   Socke.java
/**
* Socken sind spezielle Kleidungsstücke.
*/

import java.io.*;

public class Socke extends Kleidung implements Serializable
{
/**
* Erzeugt ein neues Socken-Objekt mit der Farbe Schwarz.
*/
Socke()
{
super( "schwarz" );
}

/**
* Überschrieben von der Oberklasse.
*/
public String getName()
{
return "Socke";
}
}

Wir starten javadoc im Verzeichnis, in dem auch die Klassen liegen, und bekommen eine Reihe von HTML-Dokumenten.

Möchten wir Dokumentation für das gesamte Verzeichnis erstellen, so geben wir alle Dateien mit der Endung .java an:

javadoc *.java

Generierte Dateien

Für jede öffentliche Klasse erstellt JavaDoc eine HMTL-Datei. Sind Klassen nicht öffentlich, muss ein Schalter angegeben werden. Die HTML-Dateien werden zusätzlich mit Querverweisen zu den anderen dokumentieren Klassen versehen. Daneben erstellt JavaDoc weitere Dateien:

gp  index-all.html
Die Übersicht aller Klassen, Schnittstellen, Ausnahmen, Methoden, Felder in einem Index.
gp  overview-tree.html
Zeigt in einer Baumstruktur die Klassen an, damit die Vererbung deutlich sichtbar ist.
gp  allclasses-frame.html
Anzeige aller dokumentierter Klasse in allen Unterpaketen.
gp  deprecated-list.html
Liste der veralteten Methoden und Klassen.
gp  serialized-form.html
Listet alle Klassen auf, die Serializable implementieren. Jedes Attribut erscheint mit einer Beschreibung in einem Absatz.
gp  help-doc.html
Eine Kurzbeschreibung von JavaDoc.
gp  index.html
JavaDoc erzeugt eine Ansicht mit Frames. Das ist die Hauptdatei, die die rechte und linke Seite referenziert. Die linke Seite ist die Datei allclasses-frame.html. Rechts im Frame wird bei fehlender Paketbeschreibung die erste Klasse angezeigt.
gp  stylesheet.css
Formatvorlage für HTML-Dateien, in der sich Farben und Zeichensätze einstellen lassen, die dann alle HTML-Dateien nutzen.
gp  packages.html
Eine veraltete Datei. Sie verweist auf die neuen Dateien.

Schalter für das Programm javadoc

Über die umfangreichen Parameter informiert eine HTML-Datei, die beim Java-SDK beigelegt ist.

Beispiel Für die Java API-Dokumentation haben die Entwickler eine ganze Reihe von Schaltern eingesetzt. Umgebungsvariablen machen den Aufruf besser deutlich.

WINDOWTITLE = 'Java Platform 1.2 
Final API Specification'
DOCTITLE = 'Java<sup><font size="-2">TM</font></sup> Platform 1.2 Final\
API Specification'
HEADER = '<b>Java Platform 1.2</b><br><font size="-1">Final</font>'
BOTTOM = '<font size="-1"><a href="http://java.sun.com/cgi-bin/\
bugreport.cgi">Submit a bug or feature</a><br><br>Java is a\
trademark or registered trademark of Sun Microsystems, Inc. in the\
US and other countries.<br>Copyright 1993-1998 Sun Microsystems,\
Inc. 901 San Antonio Road,<br>Palo Alto, California, 94303, U.S.A.\
All Rights Reserved.</font>'
GROUPCORE = '"Core Packages" "java.*:com.sun.java.*:org.omg.*"
GROUPEXT = '"Extension Packages" "javax.*"'

javadoc -sourcepath /jdk/src/share/classes \
-d /jdk/build/api \
-use \
-splitIndex \
-windowtitle $(WINDOWTITLE) \
-doctitle $(DOCTITLE) \
-header $(HEADER) \
-bottom $(BOTTOM) \
-group $(GROUPCORE) \
-group $(GROUPEXT) \
-overview overview-core.html \
-J-Xmx180m \
java.lang java.lang.reflect \
java.util java.io java.net \
java.applet \

Galileo Computing

26.4.4 JavaDoc und Doclets  downtop

Die Ausgabe von JavaDoc kann den eigenen Bedürfnissen angepasst werden, in dem Doclets eingesetzt werden. Ein Doclet ist ein Java-Programm, das auf der Doclet-API aufbaut und die Ausgabedatei schreibt. Das Programm liest dabei wie das bekannte JavaDoc-Tool die Quelldateien ein und erzeugt daraus ein beliebiges Ausgabeformat. Dieses Format kann selbst gewählt und implementiert werden. Wer also neben dem von JavaSoft beigefügten Standard-Doclet für HTML-Dateien Framemaker-Dateien (MIF) oder RTF-Dateien erzeugen möchte, muss nur ein eigenes Doclet programmieren. Daneben dient ein Doclet aber nicht nur der Schnittstellendokumentation. So kann ein Doclet auch dokumentieren, ob es zu jeder Methode auch eine Dokumentation gibt, oder ob jeder Parameter und Rückgabewert beschrieben ist.


Galileo Computing

26.4.5 Doclets programmieren  downtop

Die Doclets sind normale Java-Programme, die eine spezielle Doclet API benutzen, um an die Informationen der Quelltexte zu kommen, denn das Parsen wird uns schon abgenommen. Die Funktionen dazu sitzen in dem Paket sun.tools.javadoc. Das Paket ist also kein Teil der Core-API. Somit hängen die Klassen auch nicht im src-Baum. Werden die JDK-Dokumentationen installiert, so liegen die Quelldateien für das Standard-Doclet im Verzeichnis docs/ tooldocs/javadoc/source.

Doclets besitzen weder eine init()- noch eine main()-Methode zum Starten des Parsevorgangs. Hier ist der Beginn durch die Methode start() gekennzeichnet. Die Signatur ist

public static boolean start( Root 
root )

Eine Klasse Root wird als Parameter übergeben. Sie dient als Einstiegspunkt und verwaltet Informationen über die zu überprüfenden Pakete, Klassen, Interfaces und Parameter in der Kommandozeile. Um einen Einstieg zu bekommen, schauen wir uns ein kleines Doclet an. Es ist in einer Klasse ListDoclet eingebunden. In einigen Implementierungen ist die abstrakte Klasse Doclet erweitert:

import com.sun.javadoc.*;

public class ListDoclet
{
public static boolean start( RootDoc root )
{
ClassDoc[] classes = root.classes();

for ( int i = 0; i < classes.length; i++ )
System.out.println( classes[i] );

return true;
}
}

Die Klasse Root hat eine Methode classes(), die eine Liste zu parsender Klassen zurückgibt. classes() liefert dazu ein ClassDoc-Objekt und jedes von ihnen repräsentiert eine Klasse. In einer Schleife geben wir nun alle Klassen aus. Die toString()-Methode ist auf ClassDoc-Objekte so implementiert, dass sie den Namen der Klasse ausgibt.

Da Doclets ganz normale Java-Programme sind, müssen sie zunächst kompiliert werden. Da sich sun.tools.javadoc jedoch nicht im vordefinierten Jar-Archiv befindet (»jre/lib/rt.jar«), sondern in einem speziellen Tool-Archiv (unter Windows »lib/tools.jar«), ist dies beim Übersetzen mit anzugeben.

javac -classpath C:\jdk1.2\lib\tools.jar 
ListDoclet.java

Nun kann es dem Programm JavaDoc mit der Option -doclet übergeben werden:

$ javadoc -doclet ListDoclet MyClass.java

Anschließend liefert unser Doclet die gewünschte Ausgabe, den String MyClass. Ist die Option -doclet nicht festgesetzt, so verwendet JavaDoc das Standard-Doclet, welches die API-Dokumentation im HTML-Format erzeugt. Das Programm auf die eigene Klasse angesetzt, liefert als Ausgabe

Constructing Javadoc information...
javadoc: warning – Cannot find class type RootDoc
ListDoclet
1 warnings

Galileo Computing

26.4.6 Das Standard-Doclet  downtop

Um eine HTML-Dokumentation mit Verweisen und Frames zu erzeugen, muss dass Doclet natürlich wesentlich umfangreicher sein. Wir wollen uns daher mit dem Standard-Doclet beschäftigen. Über dieses kommen wir dann leichter zu unserer eigenen Beschreibung der APIs. Wie schon beschrieben, wird das Standard-Doclet immer dann benutzt, wenn die Option -doclet ohne Parameter benutzt wird. Intern sind also

$ javadoc MyClass.java

und

$ javadoc -doclet \
com.sun.tools.doclets.standard.Standard MyClass.java

gleich.

An diesem Aufruf sehen wir schon, dass die Klasse, die die start(Root)-Methode besitzt, Standard heißt. Neben dieser Standard-Klasse gibt es noch weitere Klassen, die für das Standard-Doclet programmiert wurden. Wir können uns diese auch für unsere eigenen Doclets zu nutze machen. Nachfolgend eine Tabelle, in der die Klassen aufgelistet sind, die für die Erstellung der HTML-Dokumentation wichtig sind:

gp  Standard
Einstiegspunkt für JavaDoc mit der start()-Methode. Hier wird die Erzeugung aller HTML-Seiten koordiniert.
gp  HtmlWriter
Diese Klassen übernimmt das Schreiben der verschiedenen HTML-Tags.
gp  HtmlDocWriter
Eine Erweiterung von HtmlWriter, die zusätzlich die Hyperlinks verwaltet. Zudem kümmert sich die Klasse um die Links in der Kopf- und Fußzeile der HTML-Seiten.
gp  PackageIndexWriter
Sie generiert eine Datei mit allen Paketen, die auf der Kommandozeile von JavaDoc übergeben wurden. In der Regel heißt die Datei packages.html. Beim JDK ist dies die Startseite, wenn wir die Seite »Java Platform API Specification« anfordern.
gp  PackageIndexFrameWrite
Diese Klasse erzeugt eine Liste von Verweisen im linken oberen Frame (falls die Ausgabe in Frames ist). Die Datei heißt packages-frame.html.
gp  PackageFrameWriter
Jede Klasse eines Pakets ist in der Datei package-frame-<package-name>.html aufgeführt. Der Inhalt des Frames liegt in der linken unteren Ecke des Frame-Sets.
gp  FrameOutputWriter
Falls die Dokumentation in der Frame-Ansicht gewünscht ist, so liegt in frame.html die Verwaltung der vier Fenster.
gp  PackageWriter
Diese Klasse erzeugt eine Seite eines Pakets, die eine Liste aller Interfaces und Klassen enthält, die in der Kommandozeile von JavaDoc angegeben sind. Eine aus dem Awt-Paket erzeugte Datei heißt package-java.awt.html.
gp  ClassWriter
Mit dieser Klasse wird eine HTML-Seite für jedes Interface oder jede Klasse erzeugt. Beispiel dafür ist java.awt.Button.html.
gp  SingleIndexWriter
Dies erzeugt eine Index-Datei mit einer Liste, der in den Klassen definierten Elemente (Klassenname, Methoden, Interfaces, Konstanten). (Die Option -breakindex darf nicht gesetzt sein.)
gp  SplitIndexWriter
Je eine Index-Dateie für einen Buchstaben wird erzeugt. Dies ist die Einstellung für die -breakindex-Option. Ein Beispiel ist 1-index.html für den Buchstaben A.
gp  TreeWriter
Dies erzeugt eine Baumstruktur, in der die Vererbungshierachie aufgelistet ist. In der JDK-Dokumentation die Datei tree.html.
gp  DeprecatedListWriter
Sie erzeugt eine Datei mit dem Namen deprecatedlist.html, in der alle veralteten APIs aufgeführt sind.

Methoden in der Implementierung des Standard-Doclets

Um ein Gefühl für die Doclet-Programmierung zu bekommen, werfen wir einen Blick auf die Implementierung des Standard-Doclets. Diese Klasse besitzt eine statische Variable (Configuration) und eine Reihe von Methoden:

gp  boolean start( Root root )
Die nötige Start-Methode.
gp  public static Configuration configuration()
Erzeugt eine Configuration, falls es noch keine gibt.
gp  protected void startGeneration( Root root )
Beginnt mit der Datei-Erzeugung. Sie ruft die jeweiligen Methoden der Writer-Objekte auf. Als allererstes wird TreeWriter aufgerufen, damit die Klassenhierarchie bekannt ist und diese für die anderen Writer zur Verfügung steht.
gp  protected void startGenerationOneOne( Root root )
Wie startGeneration(), nur für das alte 1.1-Format.
gp  protected void generateClassCycle( ClassDoc[] arr,ClassTree classtree )
Erzeugt ein ClassWriter-Objekt zur Dokumentation jeder Klasse, das in dem Array ClassDoc[] auftaucht.
gp  public static int optionLength( String option )
Überprüft Doclet-Optionen der Statuszeile. null heißt, dass die Option unbekannt ist. Negative Argumente zeigen einen Fehler an.

Zusammenfassung der Klassen des Pakets com.sun.tools.javadoc

Damit wir uns im folgenden Kapitel besser zurechtfinden, listen wir an dieser Stelle die Klassen des Pakets com.sun.tools.javadoc auf. Das Paket enthält nur ein Interface (Type), das einen Java-Typ beschreibt (Objektverbindung, Primitiver Datentyp).

Tabelle 26.4   Klassen im Paket sun.tools.javadoc
Klasse Beschreibung
ClassDoc Eine Java-Klasse
ConstructorDoc Ein Konstruktor einer Klasse
Doc Abstrakte Basisklasse für alle Doc-Klassen
Doclet Dokumentiert die Methoden eines Doclets, abstrakt
ExecutableMemberDoc Methode oder Konstruktor einer Klasse
FieldDoc Eine Variable der Klasse
MemberDoc Abstrakte Klasse, die Gemeinsamkeiten von Feldern,
Konstruktoren und Methoden verwalten
MethodDoc Eine Methode der Klasse
PackageDoc Informationen über ein Paket
ParamTag Ein @param Dokumentations-Tag
Parameter Informationen über Parameter
ProgramElementDoc Abstrakte Klasse, verwaltet ein Programm-Element wie Klasse, Interface, Feld, Konstruktor, Methode
Root Informationen vom Start
SeeTag Das @see Dokumentations-Tag
Tag Ein Dokumentation-Tag wie @since, @author, @version
ThrowsTag @throws- oder @exception-Tag


Galileo Computing

26.5 Dienstprogramme zur Signierung von Applets  downtop

Wir wollen uns in diesem Abschnitt mit einigen Werkzeugen beschäftigen, die zur Signierung von Applets vom Java-SDK in der Standardinstallation angeboten werden. Zum Signieren von Applikationen sowie Applets und zur Vergabe der Zugriffsrechte und –beschränkungen stellt Sun die Dienstprogramme keytool, jarsigner und policytool bereitet.


Galileo Computing

26.5.1 keytool  downtop

Mit dem Programm keytool lassen sich öffentliche und private Schlüssel erzeugen, die in einer passwortgeschützten und verschlüsselten Datei abgelegt werden. Die Datei hat standardmäßig den Namen .key