Beginnen wir mit zwei einfachen Klassen:
package com.michaelt.so.supers;
public class Sup {
int methodA(int a, int b) {
return a + b;
}
}
und dann
package com.michaelt.so.supers;
public class Sub extends Sup {
@Override
int methodA(int a, int b) {
return super.methodA(a, b);
}
}
Kompilieren von Methode A und Betrachten des Bytecodes, den man erhält:
methodA(II)I
L0
LINENUMBER 6 L0
ALOAD 0
ILOAD 1
ILOAD 2
INVOKESPECIAL com/michaelt/so/supers/Sup.methodA (II)I
IRETURN
L1
LOCALVARIABLE this Lcom/michaelt/so/supers/Sub; L0 L1 0
LOCALVARIABLE a I L0 L1 1
LOCALVARIABLE b I L0 L1 2
MAXSTACK = 3
MAXLOCALS = 3
Und Sie können genau dort mit der invokespecial-Methode sehen, dass die Suche nach der Sup-Klasse methodA () durchgeführt wird.
Der aufrufspezifische Opcode hat die folgende Logik:
- Wenn C eine Deklaration für eine Instanzmethode mit demselben Namen und Deskriptor wie die aufgelöste Methode enthält, wird diese Methode aufgerufen. Der Suchvorgang wird beendet.
- Andernfalls wird, wenn C eine Oberklasse hat, dieselbe Suchprozedur rekursiv unter Verwendung der direkten Oberklasse von C ausgeführt. Die aufzurufende Methode ist das Ergebnis des rekursiven Aufrufs dieser Suchprozedur.
- Andernfalls wird ein AbstractMethodError ausgelöst.
In diesem Fall gibt es in seiner Klasse keine Instanzmethode mit demselben Namen und Deskriptor, sodass das erste Aufzählungszeichen nicht ausgelöst wird. Die zweite Kugel wird jedoch - es gibt eine Superklasse und sie ruft die Methode A des Super auf.
Der Compiler integriert dies nicht und es gibt keine Kopie der Quelle von Sup in der Klasse.
Die Geschichte ist jedoch noch nicht fertig. Dies ist nur der kompilierte Code. Sobald der Code die JVM erreicht,kann sich HotSpot beteiligen.
Leider weiß ich nicht , dass viel über sie, so dass ich in dieser Angelegenheit Autorität ansprechen wird und gehen Inlining in Java , wo gesagt wird , dass HotSpot können Methoden inline (auch nicht-final - Methoden).
Wenn Sie zu den Dokumenten gehen , wird darauf hingewiesen, dass diese Informationen eingefügt werden können, wenn ein bestimmter Methodenaufruf zu einem Hot Spot wird, anstatt diese Suche jedes Mal durchzuführen. Dadurch wird der Code effektiv von Sup methodA () in Sub methodA () kopiert.
Dies erfolgt zur Laufzeit im Speicher, basierend auf dem Verhalten der Anwendung und den Optimierungen, die zur Beschleunigung der Leistung erforderlich sind.
Wie in HotSpot Internals for OpenJDK angegeben, werden "Methoden häufig inline dargestellt. Statische, private, endgültige und / oder" spezielle "Aufrufe lassen sich leicht einfügen."
Wenn Sie sich mit den Optionen für die JVM-XX:MaxInlineSize=35
befassen, finden Sie eine Option von (35 ist die Standardeinstellung), die die maximale Anzahl von Bytes darstellt, die inline gesetzt werden können. Ich werde darauf hinweisen, dass Java aus diesem Grund gerne viele kleine Methoden hat - weil sie leicht eingefügt werden können. Diese kleinen Methoden werden schneller , wenn sie mehr genannt werden , weil sie können inlined werden. Und während man mit dieser Zahl spielen und sie größer machen kann, kann dies dazu führen, dass andere Optimierungen weniger effektiv sind. (Verwandte SO-Frage: HotSpot JIT-Inlining-Strategie, die eine Reihe anderer Optionen aufzeigt, um einen Blick auf die Internals von Inlining zu werfen, die HotSpot durchführt).
Also nein - der Code wird zur Kompilierungszeit nicht eingefügt. Und ja - der Code könnte sehr gut zur Laufzeit eingefügt werden, wenn Leistungsoptimierungen dies rechtfertigen.
Und alles, was ich über HotSpot-Inlining geschrieben habe, gilt nur für HotSpot JVM, das von Oracle vertrieben wird. Wenn Sie sich die Liste der virtuellen Java-Maschinen von Wikipedia ansehen , gibt es viel mehr als nur HotSpot, und die Art und Weise, wie diese JVMs mit Inlining umgehen, kann völlig anders sein als oben beschrieben. Apache Harmony, Dalvik, ART - dort kann es anders laufen.