Java-Programme kompilieren und ausführen
Nutze javac zum Kompilieren von .java-Dateien in .class-Bytecode und den java-Launcher zum Ausführen auf der JVM.
Ein Java-Programm durchläuft zwei Phasen, bevor es eine Ausgabe erzeugt. Zunächst wandelt der Compiler deine .java-Quelldateien in plattformneutralen Bytecode (.class-Dateien) um. Dann lädt die JVM diesen Bytecode und führt ihn aus. Das Verständnis beider Phasen ermöglicht es dir, Classpath-Fehler, Packaging und die seltsamen Randfälle zu durchschauen, die gelegentlich auftauchen.
Dieses Kapitel führt durch die Toolchain — javac, java und jshell — sowie das Dateilayout, das die Tools erwarten.
Die Toolchain
Wenn du das JDK installierst, erhältst du drei Befehle, die du ständig verwenden wirst:
javac— der Java-Compiler. Nimmt.java-Quelldateien und erzeugt.class-Dateien.java— der Launcher. Lädt die JVM, findet eine Klasse anhand ihres Namens und führt derenmain-Methode aus.jshell— eine interaktive REPL (Read-Eval-Print-Loop) zum Ausprobieren von Code-Schnipseln, ohne ein vollständiges Programm schreiben zu müssen. Seit Java 9 verfügbar.
Du kannst ihre Verfügbarkeit prüfen, indem du jeden Befehl mit -version ausführst:
javac -version
java -version
jshell --versionEine einzelne Quelldatei kompilieren
Angenommen, du hast diese Datei als Greeting.java gespeichert:
public class Greeting {
public static void main(String[] args) {
System.out.println("Hello from javac!");
}
}Kompiliere sie:
javac Greeting.javaWenn keine Fehler auftreten, siehst du eine neue Datei im selben Verzeichnis namens Greeting.class. Das ist der Bytecode. Führe ihn aus:
java GreetingHello from javac!Beachte, dass du den Klassennamen übergibst, nicht den Dateinamen. java Greeting.class ist falsch; ebenso java Greeting.java.
Ein Programm mit Paketen kompilieren
Echte Programme sind in Pakete organisiert, die ihre Verzeichnisstruktur widerspiegeln. Eine Klasse, die als package com.example.greet; deklariert ist, muss in com/example/greet/ liegen.
project/
└── src/
└── com/example/greet/
└── Greeting.java// src/com/example/greet/Greeting.java
package com.example.greet;
public class Greeting {
public static void main(String[] args) {
System.out.println("Hello with packages!");
}
}Aus dem project/-Verzeichnis heraus kompilieren und mit dem vollqualifizierten Klassennamen ausführen:
javac -d out src/com/example/greet/Greeting.java
java -cp out com.example.greet.Greeting-d outweistjavacan, generierte.class-Dateien in dasout/-Verzeichnis zu legen (dabei wird die Paket-Verzeichnisstruktur neu erstellt).-cp outweistjavaan, Klassen imout/-Classpath zu suchen.com.example.greet.Greetingist der vollqualifizierte Klassenname — das Paket, ein Punkt und die Klasse.
In der Praxis würdest du ein Build-Tool (Maven oder Gradle, das später in diesem Buch behandelt wird) verwenden, um all das zu erledigen. Aber zu wissen, was sie intern tun, hilft, wenn etwas nicht funktioniert.
Quelldatei-Modus (Einzeldatei-Programme)
Seit Java 11 kannst du javac für Ein-Datei-Programme vollständig überspringen:
java Greeting.javaDer Launcher kompiliert im Speicher und führt das Ergebnis sofort aus — es wird keine .class-Datei auf die Festplatte geschrieben. Das ist ideal für schnelle Skripte und Buchübungen.
Der Quelldatei-Modus funktioniert nur, wenn das Programm in eine einzelne .java-Datei passt. Sobald du deinen Code auf zwei Quelldateien aufteilst, wechsle zurück zu javac (oder einem Build-Tool), um sie gemeinsam zu kompilieren.
jshell — die interaktive REPL
jshell ermöglicht es dir, Java-Ausdrücke und -Anweisungen Zeile für Zeile einzugeben, genau wie eine Python- oder Node-REPL:
$ jshell
| Welcome to JShell -- Version 21.0.4
| For an introduction type: /help intro
jshell> int x = 21
x ==> 21
jshell> int y = 21
y ==> 21
jshell> x + y
$3 ==> 42
jshell> System.out.println("Hello!")
Hello!
jshell> /exitDu brauchst keine Klasse, keine main-Methode und nicht einmal Semikolons für einfache Ausdrücke. Es ist eine hervorragende Möglichkeit, die Standardbibliothek zu erkunden, ohne ein Projekt einzurichten.
Aus der IDE ausführen
Jede Java-IDE — IntelliJ, Eclipse, VS Code — ruft intern javac und java auf, wenn du auf Run klickst. Die IDE verwaltet auch den Classpath, zeigt Compilerfehler direkt im Code an und zeigt die Programmausgabe in einem Konsolenbereich. Du musst die Kommandozeile nicht verwenden, aber zu wissen, was die IDE tut, macht das Debuggen von Build-Problemen erheblich schneller.
Ein live Beispiel
Der ausführbare Block unten durchläuft denselben javac → java-Zyklus auf unserem Server jedes Mal, wenn du Run drückst:
Bearbeite den Code, drücke Run, und der Server kompiliert deinen geänderten Quellcode und gibt aus, was das Programm produziert.
Häufige Compilerfehler
Einige Fehler, denen du oft begegnen wirst:
class Greeting is public, should be declared in a file named Greeting.java— der Dateiname und der Name der öffentlichen Klasse müssen exakt übereinstimmen.error: cannot find symbol— meistens ein Tippfehler, ein fehlendesimportoder eine Klasse, die sich nicht im Classpath befindet.';' expected— ein fehlendes Semikolon am Ende einer Anweisung.error: package x.y.z does not exist— das Paketverzeichnis befindet sich nicht im Classpath, oderjavacwurde auf das falsche Quellverzeichnis verwiesen.
Im Zweifelsfall lies die Fehlermeldung — die Diagnosen von javac sind ungewöhnlich klar.
Was kommt als nächstes
Mit dem Tooling in den Fingern beginnt der nächste Teil des Buches mit der Sprache selbst: Java-Variablen, Datentypen und der Rest der Syntax-Grundlagen.