2009-10-01 3 views
56

Я читаю this article о том, как JVM вызывает методы, и я думаю, что получил большую часть этого. Тем не менее, я все еще испытываю трудности с пониманием необходимости в invokeinterface.В чем смысл invokeinterface?

Как я понимаю, класс в основном имеет виртуальную таблицу методов и при вызове метода с invokevirtual или invokeinterface с этой виртуальной таблицей.

В чем же разница между методом, определенным на интерфейсе, и методом, определенным в базовом классе? Почему разные байткоды?

description of the instructions также выглядит очень похоже.

Статья, похоже, утверждает, что таблица методов интерфейса может иметь «разные смещения» каждый раз при вызове метода. Я не понимаю, почему интерфейс будет иметь таблицу методов вообще, поскольку ни один объект не может иметь интерфейс как его фактический тип.

Что мне не хватает?

+3

См. [Эффективное внедрение Java-интерфейсов: Invokeinterface считается безвредным] (http://www.research.ibm.com/people/d/dgrove/papers/oopsla01.pdf). –

+1

В нем есть таблица виртуальных методов. Сама таблица вообще не виртуальна;) –

ответ

78

Каждый класс 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".

+4

«всегда нужно искать полную таблицу без возможности для стиля оптимизации, который имеет invokevirtual». Следует отметить, что он не всегда * должен искать в таблице, так как он может сделать другой стиль оптимизации , Для получения дополнительной информации см. Связанную «считающуюся безвредную» бумагу. –

1

Сравнивая обе команды в JVM Spec, самое первое отличие состоит в том, что invokevirtual проверяет доступность метода во время поиска, а invokeinterface - нет.

+0

Интересно, но может ли это быть все, что нужно? – itsadok

+0

Существует больше различий в этом (как объясняется в другом месте, процесс поиска метода отличается), но это отличие происходит от того, что все методы в интерфейсе (по крайней мере до Java 8) являются общедоступными. Поэтому проверка видимости доступа к методам через интерфейс не требуется, поскольку они должны быть общедоступными, что означает, что все коды могут получить к ним доступ. –