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 erzeugt
    jar -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

Copyright © 2025 Thomas Smits