© Excellent backgrounds/Shutterstock.com
Kolumne: Java-Trickkiste

Der JIT-Compiler von Hotspot


Die Hotspot-JVM liest Class-Dateien ein und führt das entsprechende Java-Programm aus. An irgendeiner Stelle „kompiliert“ sie das Programm noch einmal und wendet dabei ausgefeilte Verfahren an, sodass Java-Programme bemerkenswert schnell laufen. Das ist in etwa das, was man beim Entwickeln von Geschäftsanwendungen über den JIT-Compiler wissen muss. Wenn man aber z. B. performancekritischen Code schreibt oder einfach nur neugierig ist, lohnt sich ein Blick hinter die Kulissen.

Aber der Reihe nach: Wieso überhaupt Compiler? Der Java-Compiler kompiliert den Quellcode doch schon in Bytecode – wozu noch ein Compiler?

Der Grund ist die Performance. Eine JVM kann direkt Bytecode ausführen, aber das ist nicht besonders schnell. Sie muss sich dann jeden einzelnen Programmschritt ansehen und entscheiden, was sie damit tun soll, und ein solcher Interpreter erzeugt eben Overhead. Ein JIT-Compiler (JIT steht für „Just in Time“, also in etwa „erst dann, wenn man es braucht“) wird aktiv, während das Programm schon läuft, und übersetzt einzelne Methoden in Maschinencode. Diese Methoden laufen dann direkt auf dem Prozessor, ohne dass ein Interpreter aktiv werden muss, und sind sehr viel schneller.

Hotspot bei der Arbeit zusehen

Wenn man wissen will, welche Methoden Hotspot wann kompiliert, kann man das entsprechende Logging mit dem Schalter -XX:+PrintCompilation aktivieren. Dieser Schalter erzeugt jedes Mal eine Zeile, wenn eine Methode JIT-kompiliert wird.

Die am häufigsten aufgerufenen Methoden werden zuerst kompiliert. Welche das sind, hängt natürlich vom jeweiligen Programm ab, aber z. B. String.hashCode() oder der Konstruktor von Object sind häufig früh dabei. In der Liste tauchen dieselben Methoden meist mehrmals auf. Das liegt daran, dass Hotspot mehrstufig arbeitet. Zunächst übersetzt er eine Methode in einfachen, wenig optimierten Maschinencode. Wenn sie besonders häufig verwendet wird, kompiliert er sie ein zweites (oder auch drittes) Mal und investiert dabei Zeit und Speicher für Optimierungen wie Inlining (s. u.).

Der Schalter -XX:+PrintAssembly veranlasst Hotspot dazu, den jeweils tatsächlich erzeugten Assem­bler-Code auszugeben. Man muss dabei zusätzlich den Schalter -XX:+UnlockDiagnosticVMOptions angeben. Außerdem muss man die Bibliothek hsdis-amd64.dll (bzw. ­hsdis-amd64.so) in das lib-Verzeichnis der JRE legen [1]. Sie dient dazu, den Maschinencode menschenlesbar zu formatieren. Auch wenn man den Assembler-Output nicht im Detail untersucht (oder versteht...

Neugierig geworden?

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang