HOWTO · Java
Java-Inline-Funktion
Java kennt keine `inline`-Deklaration auf Quelltextebene. Die JVM kann Methodenaufrufe zur Laufzeit inline einfügen. Das Beispiel vergleicht einen Methodenaufruf mit gleichwertigen direkten Anweisungen.
Auf dieser Seite
Java kennt keine inline-Funktionsdeklaration auf Quelltextebene. Wer nach einer Inline-Funktion in Java sucht, meint damit meist Methoden-Inlining: eine Laufzeitoptimierung, bei der eine JVM einen Methodenaufruf möglicherweise durch die Anweisungen der Methode ersetzt. Sie schreiben gewöhnliche Java-Methoden; die JVM entscheidet während der Programmausführung, ob sie Aufrufe inline einfügt.
Was ist Methoden-Inlining in Java?
Bei einem Methodenaufruf wird die Ausführung normalerweise an die Methode übergeben und ihr Ergebnis zurückgegeben. Beim Inlining kann dieser Aufruf im kompilierten Maschinencode entfallen, indem die Anweisungen der Methode an der Aufrufstelle eingefügt werden. Das ist eine JVM-Optimierung, keine Änderung am Java-Quelltext und nichts, was Sie durch eigenes Kopieren von Code ausführen. Der Java-Compiler kompiliert den Quelltext weiterhin in Klassendateien; für die Laufzeitausführung und Optimierung ist die JVM zuständig.
Inlining bedeutet auch nicht, dass jede Methode überall erweitert wird. Die Laufzeitumgebung muss das Verhalten des Programms bewahren und kann einen Aufruf beibehalten, wenn sich Inlining nicht eignet. Schreiben Sie verständliche Methoden und überlassen Sie diese Implementierungsentscheidung der JVM.
Wie die HotSpot-JVM Methoden-Inlining durchführt
Der Just-in-Time-Compiler (JIT) von HotSpot kann geeignete Methodenaufrufe im Rahmen der Laufzeitoptimierung inline einfügen. Die Entscheidung hängt vom Code und den Laufzeitbedingungen ab; sie ist keine Garantie der Java-Sprache. Beschreiben Sie Inlining daher weder als in jeder JVM stets aktiviert, noch verlassen Sie sich darauf, dass ein implementierungsspezifisches Flag für dieses Beispiel erforderlich ist. Das folgende Beispiel veranschaulicht gleichwertige Berechnungen, steuert aber nicht, was HotSpot intern kompiliert, und macht dies auch nicht sichtbar.
Erstellen Sie ein Java-Beispiel zum Vergleich eines Methodenaufrufs mit gleichwertigen Anweisungen
Bei der ersten Berechnung werden addBonus und anschließend score aufgerufen. Die zweite führt dieselbe Rechnung direkt aus. Beide beginnen mit demselben Wert. So lassen sich die Ergebnisse vergleichen, ohne zu behaupten, dass die JVM einen der beiden Aufrufe tatsächlich inline eingefügt hat.
Führen Sie dieses Beispiel aus. Die Bezeichnungen in der unveränderten Codeausgabe bleiben auf Englisch: „Method calls“ kennzeichnet das Ergebnis der Methodenaufrufe, „Direct statements“ das der direkten Anweisungen.
public class Main {
static int addBonus(int score) {
return score + 2;
}
static int score(int value) {
return value * 3;
}
public static void main(String[] args) {
int byMethodCalls = score(addBonus(4));
int value = 4;
int byStatements = (value + 2) * 3;
System.out.println("Method calls: " + byMethodCalls);
System.out.println("Direct statements: " + byStatements);
}
}
Method calls: 18
Direct statements: 18
Das Beispiel kompilieren und ausführen
Speichern Sie den Quelltext in einem leeren Arbeitsverzeichnis als Main.java. Kompilieren und starten Sie das Programm von dort aus mit einem JDK, das über PATH erreichbar ist:
Führen Sie in diesem Verzeichnis zuerst javac Main.java und danach java Main aus. Die Befehle passen zum gezeigten Klassen- und Dateinamen und benötigen keine JVM-Tuningoptionen. Der bereitgestellte Lauf genau dieses Beispiels wurde erfolgreich abgeschlossen und gab die oben gezeigte Ausgabe aus.
Was die Ergebnisse zeigen und was nicht
Vergleichen Sie beim Ausführen des Programms die beiden ausgegebenen Werte: Sie sollten übereinstimmen, weil die Methodenaufrufe und der direkte Ausdruck dieselbe Rechnung verwenden. Damit ist die Ergebnisgleichheit dieses kleinen Beispiels gezeigt. Daraus geht nicht hervor, ob die JVM eine der Methoden inline eingefügt hat. Gleiche Werte sagen auch nichts darüber aus, welche Variante schneller läuft; dafür wäre ein eigener, kontrollierter Benchmark nötig. Verwenden Sie also gewöhnliche Java-Methoden für gut lesbaren Quelltext und betrachten Sie Inlining als mögliche Laufzeitoptimierung, nicht als Funktion, die Sie deklarieren, oder als Leistungsergebnis, das sich aus dieser Ausgabe ableiten lässt.