Java-Archive (JAR)
Klassische Programmiersprachen
In klassischen Programmiersprachen besteht die Programmerzeugung aus zwei Schritten
- Übersetzen (compile) – die Quelldateien werden einzeln in plattformspezifischen Maschinencode übersetzt
- Binden (link) – alle Teile des Programms werden zu einer einzigen ausführbaren Datei (Executable) zusammengebunden
- statisches Binden – das erzeugte Executable enthält alle Programmteile und alle Bibliotheken
- dynamisches Binden – nur Teile des Programms sind im Executable enthalten, andere Teile (meistens Bibliotheken) werden bei Bedarf zur Laufzeit nachgeladen
Klassische Programmiersprachen (C, C++, Modula 2, Pascal) erzeugen ausführbare Dateien, die spezifisch für die jeweilige Plattform sind, d. h. sie enthalten Maschinenbefehle für den Prozessor der Maschine. Um die Programmierung modularisieren zu können, wird die Erzeugung einer solchen Binärdatei in zwei Schritte aufgeteilt:
- Im ersten Schritt werden die vorhandenen Quelldateien vom Compiler in Maschinencode für die Plattform übersetzt. Hierbei werden allerdings die Beziehungen zwischen den Quell-Dateien noch nicht aufgelöst, da sie einzeln übersetzt werden. Beziehungen (meist Funktionsaufrufe), die sich von einer auf die andere Quelldatei beziehen werden nur vermerkt aber noch nicht miteinander verbunden. Das Ergebnis eines solchen Schrittes bezeichnet man als Objektdatei (object file).
- In einem zweiten Schritt, sammelt ein weiteres Werkzeug, der Linker, alle benötigten Objektdateien zusammen und löst die Querbeziehungen auf, indem er die symbolischen Referenzen durch echte Funktionsaufrufe ersetzt (binden). Als Ergebnis erhält man eine Programmdatei (executable).
Beim Linken besteht die Möglichkeit entweder alle Objektdateien statisch zu einem einzigen Executable zu binden (statisches Linken) oder aber erst zu Laufzeit einzelne Teile nachzuladen (dynamisches Linken).
Compilieren und Linken (statisch)
Compilieren und Linken (dynamisch)
Compilieren und Linken bei Java
- Java kennt keine Header-Dateien, jede Java-Klasse ist selbstbeschreibend
- Verwender kann alle Meta-Informationen aus der .class-Datei beziehen
javap
dient dazu, diese Informationen auszugeben- Java kennt keinen Linker, sondern nur einen Compiler
- Klassen
- werden von der Java VM dynamisch bei Bedarf geladen
- werden erst geladen, wenn sie das erste Mal benötigt werden
- werden erst bei Bedarf von der VM intern gelinkt
- Java VM sucht die Klassen auf dem Klassenpfad (classpath) (VM-Option
-cp
oder-classpath
)
Das Übersetzen von Programmen mit Java folgt anderen Prinzipien als das Übersetzen und Linken in klassischen Programmiersprachen.
In Java existieren keine Header-Dateien, sondern der Verwender eine Klasse kann alle Informationen, die er benötigt, aus der Klasse selbst beziehen. Java-Klassen sind somit selbstbeschreibend und enthalten sowohl die Definition als auch die Deklaration von Methoden und Variablen. Man kann sich diese Meta-Informationen mit dem Tool javap
ansehen.
Bei Java existiert kein Linker, d. h. die kompilierten Klassen werden nicht in einem zusätzlichen Schritt zu einer ausführbaren Datei gebunden. An Stelle des Linkers fungiert die Java-VM, die während des Ablauf eines Programms dynamisch alle Klassen nachlädt, die von diesem benötigt werden (dynamic classloading). Natürlich müssen auch im Falle von Java die Beziehungen zwischen den Klassen aufgelöst werden und symbolische Methodenaufrufe durch echte ersetzt werden. Dieses Binden oder Linken wird aber von der VM intern zur Laufzeit durchgeführt und ist daher für den Verwender nicht sichtbar.
Damit die Java-VM die benötigten Klassen finden kann, kann man mithilfe der Kommandozeilenoption -classpath
festlegen, wo sie überall nach Klassen suchen soll.
Compilieren bei Java
Beispiel: javap
$ javap java.awt.Point
Compiled from "Point.java"
public class java.awt.Point extends java.awt.geom.Point2D
implements java.io.Serializable{
public int x;
public int y;
public java.awt.Point();
public double getX();
public double getY();
public void setLocation(double, double);
public void move(int, int);
public void translate(int, int);
public boolean equals(java.lang.Object);
public java.lang.String toString();
...
}
Das Beispiel zeigt die Ausgabe des Werkzeugs javap
für die Klasse Point
.
Java ARchive
Java Archive (JAR) – Sammlung von Java-Klassen (und Hilfsdateien) im ZIP-Format gepackt
Vorteile
- komprimiert, weniger Speicherplatzverbrauch
- eine einzelne Datei, mehr Ordnung
- zusammengehörige Klassen können gruppiert werden
- kann direkt ausgeführt werden (
java -jar foo.jar
) - können genauso auf den Klassenpfad gelegt werden, wie Verzeichnisse mit Klassen
Die große Anzahl von Klassen, die in einem Java-Projekt entstehen, legt es nah, diese in irgendeiner Form zusammenzufassen. Bei einer klassischen Programmiersprache reduziert der Linker die vielen Objektdateien durch das binden zu einigen wenigen Executables und Bibliotheken. In Java gibt es aber keinen Linker, sodass aus jeder Quelldatei mindestens eine .class-Datei entsteht.
Um Java-Klassen zusammenzufassen, verwendet man Java ARchive (JAR). In einem solchen JAR können Java-Klassen und andere Ressourcen, die das Programm zur Laufzeit benötigt, in einer ZIP-Datei verpackt werden. Hierdurch reduziert sich der Speicherplatzverbrauch und die Übersichtlichkeit steigt, wenn man zusammengehörige Klassen in einzelne Archive verpackt.
Die Java-VM kann Klassen nicht nur aus dem Dateisystem als einzelne Dateien, sondern direkt aus dem JAR-Archiv lesen, sodass keine Notwendigkeit besteht, die Archive vor der Ausführung auszupacken. Hierzu gibt man die Java-Archive als Teile des Klassenpfades an.
Weitere Vorteile von Java-Archiven
- Sicherheit – Man kann den Inhalt digital signieren und so vor Veränderungen schützen
- Sealing – Man kann festlegen, dass alle Klassen eines Paketes in einem JAR enthalten sein müssen
- Versionierung – In den Metadaten der JAR-Datei kann man Versionsinformationen für die enthaltenen Klassen ablegen
Erzeugen von JAR-Dateien
- JAR-Dateien werden mit dem Programm
jar
erzeugtjar -cvf archivname.jar dateien
- Syntax ist ähnlich zum Unix-Kommando
tar
- Zusätzlich zu den eingepackten Dateien enthält ein JAR Metadaten im
META-INF
-Verzeichnis
Erzeugung einer JAR-Datei
Einbinden von JAR-Dateien
Eigene und fremde JARs können eingebunden werden
- in Eclipse in den Projekteigenschaften unter „Java Build Path“ und Libraries
- auf der Kommandozeile bei Compiler und Java-VM über die Option
-classpath
