Java Virtual Machine - optymalizacje JIT
W tym rozdziale poznamy optymalizacje JIT.
Metoda Inlining
W tej technice optymalizacji kompilator decyduje się na zastąpienie wywołań funkcji treścią funkcji. Poniżej znajduje się przykład tego samego -
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;
}
Korzystając z tej techniki, kompilator chroni maszynę przed narzutem związanym z wykonywaniem jakichkolwiek wywołań funkcji (wymaga to wypychania i wrzucania parametrów na stos). W ten sposób wygenerowany kod działa szybciej.
Inlinowanie metod można wykonać tylko dla funkcji niewirtualnych (funkcji, które nie są zastępowane). Zastanów się, co by się stało, gdyby metoda „add” została zastąpiona w klasie podrzędnej, a typ obiektu zawierającego metodę nie byłby znany do czasu wykonania. W takim przypadku kompilator nie wiedziałby, jaką metodę wstawić. Ale jeśli metoda została oznaczona jako „ostateczna”, kompilator z łatwością wiedziałby, że może być wbudowana, ponieważ nie można jej nadpisać przez żadną podklasę. Należy pamiętać, że nie ma żadnej gwarancji, że ostateczna metoda będzie zawsze wprowadzana.
Eliminacja nieosiągalnego i martwego kodu
Kod nieosiągalny to kod, do którego nie mogą dotrzeć żadne możliwe przepływy wykonania. Rozważymy następujący przykład -
void foo() {
if (a) return;
else return;
foobar(a,b); //unreachable code, compile time error
}
Martwy kod jest również kodem nieosiągalnym, ale kompilator wypluwa w tym przypadku błąd. Zamiast tego otrzymujemy tylko ostrzeżenie. Każdy blok kodu, taki jak konstruktory, funkcje, try, catch, if, while, itp. Ma własne reguły dotyczące nieosiągalnego kodu zdefiniowane w JLS (Java Language Specification).
Stałe składanie
Aby zrozumieć koncepcję stałego składania, zobacz poniższy przykład.
final int num = 5;
int b = num * 6; //compile-time constant, num never changes
//compiler would assign b a value of 30.