
Bytecode
Bytecode ist eine Zwischenform von Programmcode: Er steht zwischen dem lesbaren Text, den Menschen schreiben, und den Befehlen, die ein Prozessor direkt ausführt. Ein Hilfsprogramm auf dem Zielgerät liest den Bytecode und setzt ihn dort in echte Maschinenbefehle um.
Programme werden von Menschen als Text geschrieben, in einer Programmiersprache wie Java oder Python. Ein Prozessor, also der Rechenchip eines Computers, versteht diesen Text nicht. Er kennt nur sehr einfache Befehle in einer festen Zahlenform, und diese Form ist bei jedem Chiptyp anders. Zwischen beide Welten schiebt man deshalb oft eine dritte Ebene: den Bytecode. Das ist eine kompakte Befehlsliste, die kein Mensch mehr bequem liest, die aber auch noch nicht an einen bestimmten Chip gebunden ist. Ein Hilfsprogramm auf dem Zielgerät liest diese Liste und führt sie aus.
Der Name kommt daher, dass die einzelnen Befehle traditionell je ein Byte belegen, also eine sehr kleine Speichereinheit. Man kann sich Bytecode als Rezept in einer Kunstsprache vorstellen. Diese Sprache versteht niemand von Natur aus, aber es gibt überall einen Dolmetscher dafür.
Warum ein Programm damit überall läuft
Ohne Zwischenschritt müsste man ein Programm für jeden Gerätetyp neu übersetzen. Ein Windows-PC, ein Mac mit Apple-Chip und ein Android-Handy verstehen jeweils andere Maschinenbefehle. Der Hersteller müsste also mehrere getrennte Versionen bauen und pflegen. Mit Bytecode entsteht nur eine einzige Datei, und jedes Gerät bringt seinen eigenen Übersetzer mit.
Genau damit wurde Java in den 1990er-Jahren groß. Der Werbespruch lautete: einmal schreiben, überall ausführen. Dasselbe Prinzip steckt heute in Python, in C# und in WebAssembly, einem Bytecode-Format für Webbrowser. Wenn im Browser ein Videoschnittprogramm oder ein 3D-Spiel läuft, steckt oft WebAssembly dahinter.
Ein zweiter Vorteil ist Sicherheit. Weil der Bytecode nicht direkt auf den Chip losgelassen wird, kann der Übersetzer vorher prüfen, was das Programm überhaupt tun darf. Ein Browser blockiert so den Zugriff auf fremde Dateien. Der Preis dafür ist Tempo: Diese Kontrolle kostet Rechenzeit.
Vom Quelltext bis zum ausgeführten Befehl
Zuerst liest ein Compiler den geschriebenen Programmtext. Ein Compiler ist ein Übersetzungsprogramm; es prüft den Text auf Fehler und wandelt ihn in Bytecode um. Dieser Schritt passiert einmal, beim Entwickler. Bei Java entsteht dabei eine Datei mit der Endung .class.
Auf dem Zielgerät übernimmt dann eine sogenannte virtuelle Maschine. Das ist kein echter Computer, sondern ein Programm, das sich wie einer verhält. Sie geht den Bytecode Befehl für Befehl durch und führt jeden aus. Ein Befehl kann etwa lauten: lege die Zahl 5 auf den Stapel, oder addiere die beiden obersten Werte.
Reines Abarbeiten Zeile für Zeile wäre langsam. Deshalb nutzen moderne Systeme einen Just-in-time-Compiler. Der beobachtet, welche Stellen im Programm besonders oft laufen, und übersetzt genau diese während der Ausführung in echte Maschinenbefehle. Ein häufiger Irrtum ist, Bytecode sei generell langsam. Bei lang laufenden Programmen kommt er heute nahe an direkt übersetzten Code heran.
Bytecode im Alltag und in Tech-Meldungen
Wer Minecraft in der Java-Version spielt, startet Bytecode. Dasselbe gilt für viele Banking-Systeme und für einen Großteil der Android-Apps. Auch Python arbeitet so: Beim ersten Start eines Skripts legt es stillschweigend Dateien mit der Endung .pyc in einem Ordner namens __pycache__ ab. Das ist der zwischengespeicherte Bytecode, damit der nächste Start schneller geht.
In Nachrichten taucht der Begriff meist in drei Zusammenhängen auf. Erstens bei WebAssembly, wenn es um schnelle Anwendungen im Browser geht. Zweitens bei Blockchain-Projekten: Verträge für Ethereum werden in Bytecode übersetzt und von allen Rechnern im Netzwerk identisch ausgeführt. Drittens bei Sicherheitslücken, weil Angreifer manipulierten Bytecode einschleusen können.
Abzugrenzen ist Bytecode von zwei Nachbarbegriffen. Quelltext ist die lesbare Fassung, die Menschen schreiben und ändern. Maschinencode ist die fertige Zahlenform für einen bestimmten Chip. Bytecode liegt genau dazwischen und ist damit weder gut lesbar noch direkt ausführbar.