Каждый класс Java связан с таблицей виртуальных методов , которая содержит «ссылки» на байт-код каждого метода класса. Эта таблица наследуется от суперкласса определенного класса и расширяется в отношении новых методов подкласса. Например,
class BaseClass {
public void method1() { }
public void method2() { }
public void method3() { }
}
class NextClass extends BaseClass {
public void method2() { } // overridden from BaseClass
public void method4() { }
}
результаты в таблицах
BaseClass
1. BaseClass/method1()
2. BaseClass/method2()
3. BaseClass/method3()
NextClass
1. BaseClass/method1()
2. NextClass/method2()
3. BaseClass/method3()
4. NextClass/method4()
Примечание, как виртуальный метод таблица NextClass
сохраняет порядок записей таблицы BaseClass
и просто переписывает «звено» method2()
который он переопределяет.
Реализация JVM может таким образом оптимизировать вызов invokevirtual
, помня, что BaseClass/method3()
всегда будет третьей записью в таблице виртуальных методов любого объекта, к которому этот метод когда-либо будет задействован.
С invokeinterface
эта оптимизация невозможна. Например, результаты иерархии
interface MyInterface {
void ifaceMethod();
}
class AnotherClass extends NextClass implements MyInterface {
public void method4() { } // overridden from NextClass
public void ifaceMethod() { }
}
class MyClass implements MyInterface {
public void method5() { }
public void ifaceMethod() { }
}
Этот класс в таблицах виртуальных методов
AnotherClass
1. BaseClass/method1()
2. NextClass/method2()
3. BaseClass/method3()
4. AnotherClass/method4()
5. MyInterface/ifaceMethod()
MyClass
1. MyClass/method5()
2. MyInterface/ifaceMethod()
Как вы можете видеть, AnotherClass
содержит метод интерфейса в своей пятой позиции и MyClass
содержит его в своем втором входе. Чтобы на самом деле найти правильную запись в таблице виртуальных методов, вызов метода с invokeinterface
всегда будет искать полную таблицу без возможности для стиля оптимизации, который делает invokevirtual
.
Есть дополнительные отличия, такие как факт, что invokeinterface
может использоваться вместе с ссылками на объекты, которые фактически не реализуют интерфейс.Поэтому invokeinterface
будет проверять во время выполнения, существует ли метод в таблице и потенциально генерировать исключение. Если вы хотите глубже погрузиться в эту тему, я предлагаю, например, "Efficient Implementation of Java Interfaces: Invokeinterface Considered Harmless".
См. [Эффективное внедрение Java-интерфейсов: Invokeinterface считается безвредным] (http://www.research.ibm.com/people/d/dgrove/papers/oopsla01.pdf). –
В нем есть таблица виртуальных методов. Сама таблица вообще не виртуальна;) –