Java Virtual Machine - JIT-Optimierungen
In diesem Kapitel erfahren Sie mehr über JIT-Optimierungen.
Methode Inlining
Bei dieser Optimierungstechnik beschließt der Compiler, Ihre Funktionsaufrufe durch den Funktionskörper zu ersetzen. Unten ist ein Beispiel für das gleiche -
int sum3;
static int add(int a, int b) {
return a + b;
}
public static void main(String…args) {
sum3 = add(5,7) + add(4,2);
}
//after method inlining
public static void main(String…args) {
sum3 = 5+ 7 + 4 + 2;
}
Mit dieser Technik erspart der Compiler dem Computer den Aufwand für Funktionsaufrufe (es müssen Parameter auf den Stapel verschoben und dort abgelegt werden). Somit läuft der generierte Code schneller.
Das Inlining von Methoden kann nur für nicht virtuelle Funktionen durchgeführt werden (Funktionen, die nicht überschrieben werden). Überlegen Sie, was passieren würde, wenn die Methode 'add' in einer Unterklasse überschrieben würde und der Typ des Objekts, das die Methode enthält, erst zur Laufzeit bekannt ist. In diesem Fall würde der Compiler nicht wissen, welche Methode inline sein soll. Wenn die Methode jedoch als 'final' markiert wäre, würde der Compiler leicht erkennen, dass sie inline sein kann, da sie von keiner Unterklasse überschrieben werden kann. Beachten Sie, dass nicht garantiert werden kann, dass eine endgültige Methode immer inline ist.
Nicht erreichbare und tote Code-Eliminierung
Nicht erreichbarer Code ist Code, auf den keine möglichen Ausführungsabläufe zugreifen können. Wir werden das folgende Beispiel betrachten -
void foo() {
if (a) return;
else return;
foobar(a,b); //unreachable code, compile time error
}
Toter Code ist ebenfalls nicht erreichbarer Code, aber der Compiler spuckt in diesem Fall einen Fehler aus. Stattdessen erhalten wir nur eine Warnung. Jeder Codeblock wie Konstruktoren, Funktionen, try, catch, if, while usw. hat seine eigenen Regeln für nicht erreichbaren Code, die in der JLS (Java Language Specification) definiert sind.
Konstante Faltung
Um das Konzept der konstanten Faltung zu verstehen, sehen Sie sich das folgende Beispiel an.
final int num = 5;
int b = num * 6; //compile-time constant, num never changes
//compiler would assign b a value of 30.