Commençons par deux classes simples:
package com.michaelt.so.supers;
public class Sup {
int methodA(int a, int b) {
return a + b;
}
}
et alors
package com.michaelt.so.supers;
public class Sub extends Sup {
@Override
int methodA(int a, int b) {
return super.methodA(a, b);
}
}
En compilant la méthode A et en regardant le code d'octet, on obtient:
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
Et vous pouvez voir juste là avec la méthode invokespecial qu'il fait la recherche contre la méthode de classe SupA ().
L' opcode invokespecial a la logique suivante:
- Si C contient une déclaration pour une méthode d'instance avec le même nom et descripteur que la méthode résolue, alors cette méthode sera invoquée. La procédure de recherche se termine.
- Sinon, si C a une superclasse, cette même procédure de recherche est effectuée récursivement en utilisant la superclasse directe de C. La méthode à invoquer est le résultat de l'invocation récursive de cette procédure de recherche.
- Sinon, une AbstractMethodError est déclenchée.
Dans ce cas, il n'y a pas de méthode d'instance avec le même nom et le même descripteur dans sa classe, donc la première puce ne va pas se déclencher. La deuxième puce le fera cependant - il y a une superclasse et elle invoque la méthode A du super.
Le compilateur n'inline pas cela et il n'y a pas de copie de la source de Sup dans la classe.
Mais l'histoire n'est pas encore terminée. Ce n'est que lecode compilé . Une fois que le code atteint la JVM, HotSpot peut s'impliquer.
Malheureusement, je ne sais pas grand-chose à ce sujet, je vais donc faire appel à l'autorité à ce sujet et aller à Inlining à Java où il est dit que HotSpot peut incorporer des méthodes (même des méthodes non définitives).
En allant dans la documentation, il est à noter que si un appel de méthode particulier devient un point chaud au lieu de faire cette recherche à chaque fois, ces informations peuvent être intégrées - en copiant efficacement le code de Sup methodA () dans Sub methodA ().
Cela se fait au moment de l'exécution, en mémoire, en fonction du comportement de l'application et des optimisations nécessaires pour accélérer les performances.
Comme indiqué dans HotSpot Internals for OpenJDK "Les méthodes sont souvent intégrées. Les invocations statiques, privées, finales et / ou" spéciales "sont faciles à intégrer."
Si vous creusez dans les options de la JVM, vous trouverez une option -XX:MaxInlineSize=35
(35 étant la valeur par défaut) qui est le nombre maximal d'octets pouvant être insérés. Je soulignerai que c'est pourquoi Java aime avoir beaucoup de petites méthodes - car elles peuvent être facilement intégrées. Ces petites méthodes deviennent plus rapides lorsqu'elles sont appelées davantage car elles peuvent être intégrées. Et bien que l'on puisse jouer avec ce nombre et l'agrandir, cela peut rendre d'autres optimisations moins efficaces. (question SO connexe: stratégie d'inclusion de HotSpot JIT qui souligne un certain nombre d'autres options pour jeter un œil aux aspects internes de l'inclusion que HotSpot fait).
Donc, non - le code n'est pas inséré au moment de la compilation. Et, oui - le code pourrait très bien être intégré à l'exécution si les optimisations de performances le justifient.
Et tout ce que j'ai écrit sur l'incrustation HotSpot s'applique uniquement à la machine virtuelle Java HotSpot distribuée par Oracle. Si vous regardez la liste des machines virtuelles Java de wikipedia, il y a bien plus que HotSpot et la façon dont ces JVM gèrent l'inline peut être complètement différente de ce que j'ai décrit ci-dessus. Apache Harmony, Dalvik, ART - les choses peuvent fonctionner différemment là-bas.