Почнемо з двох простих класів:
package com.michaelt.so.supers;
public class Sup {
int methodA(int a, int b) {
return a + b;
}
}
і потім
package com.michaelt.so.supers;
public class Sub extends Sup {
@Override
int methodA(int a, int b) {
return super.methodA(a, b);
}
}
Метод компіляціїA і перегляд байтового коду виходить:
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
І ви можете побачити прямо там, за допомогою методу invokespecial, він робить пошук по методу класу SupA ().
Invokespecial опкод має наступну логіку:
- Якщо C містить декларацію для методу екземпляра з тим самим іменем та дескриптором, що і розв'язаний метод, тоді цей метод буде застосовано. Процедура пошуку припиняється.
- В іншому випадку, якщо C має надклас, ця сама процедура пошуку виконується рекурсивно, використовуючи прямий надклас C. Метод, який слід викликати, є результатом рекурсивного виклику цієї процедури пошуку.
- Інакше піднімається AbstractMethodError.
У цьому випадку не існує жодного методу екземпляра з тим самим іменем та дескриптором у своєму класі, тому перша куля не збирається. Однак друга куля буде - є суперклас, і він викликає метод супер.
Компілятор не вказує на це рядки, і немає копії джерела Sup у класі.
Однак історія ще не закінчена. Це просто складений код. Як тільки код потрапить у JVM, HotSpot може долучитися.
На жаль, я про це не знаю багато, тому я звернусь до авторитету з цього приводу і перейду до Inlining на Яві, де сказано, що HotSpot може вбудовувати методи (навіть не завершальні методи).
Переходячи до документів , зазначається, що якщо виклик певного методу стає гарячою точкою замість того, щоб щоразу шукати цю інформацію, цю інформацію можна вводити - ефективно копіюючи код із Sup methodA () у Sub methodA ().
Це робиться під час виконання, в пам'яті, виходячи з того, як поводиться програма та які оптимізації необхідні для прискорення продуктивності.
Як зазначено в HotSpot Internals для OpenJDK, "Методи часто вказуються. Статичні, приватні, остаточні та / або" спеціальні "виклики легко вводити".
Якщо ви заглибитесь у параметри для JVM, ви знайдете варіант -XX:MaxInlineSize=35
(35 за замовчуванням), який є максимальною кількістю байтів, які можна вкласти. Я зазначу, що саме тому Java любить мати безліч методів, оскільки їх можна легко вписати. Ці маленькі методи стають швидшими, коли їх називають більше, тому що їх можна накреслити. І хоча можна грати з цим числом і збільшувати його, це може призвести до того, що інші оптимізації будуть менш ефективними. (пов'язане питання ТАК: Стратегія вбудованого проекту HotSpot JIT, яка вказує на ряд інших варіантів зазирнути до внутрішніх тексту вставки, що робить HotSpot).
Отже, ні - код не вказується під час компіляції. І так, код дуже добре може бути накреслений під час виконання, якщо цього вимагають оптимізації роботи.
І все, що я писав про вбудовування HotSpot, стосується лише HotSpot JVM, розповсюдженого Oracle. Якщо ви подивитеся на список віртуальних машин Вікіпедії, то є багато більше, ніж просто HotSpot, і спосіб, яким ці JVM обробляють вбудовані вставки, може бути зовсім іншим, ніж те, що я описав вище. Apache Harmony, Dalvik, ART - там все може працювати інакше.