В чем смысл invokeinterface?
Я читаю в этой статье о том, как JVM вызывает методы, и я думаю, что я получил большинство из них. Тем не менее, у меня все еще возникают проблемы с пониманием необходимости invokeinterface.
как я понимаю, класс в основном имеет таблицу виртуальных методов и при вызове метода с invokevirtual или invokeinterface эта виртуальная таблица консультируется.
в чем же тогда разница между методом, определенным на интерфейсе, и методом, определенным на базе класс? Почему разные байт-коды?
The описание инструкции также очень похож.
в статье, похоже, утверждается, что таблица методов интерфейса может иметь "разные смещения" каждый раз, когда вызывается метод. Я не понимаю, почему интерфейс будет иметь таблицу методов вообще, так как ни один объект не может иметь интерфейс в качестве его фактического типа.
что я упустил?
2 ответов:
каждый класс 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придется проверить на время выполнения ли метод существует в таблице и потенциально вызвать исключение. Если вы хотите погрузиться глубже в тему, я предлагаю, например,"эффективная реализация интерфейсов Java: Invokeinterface считается безвредным".
сравнение обеих инструкций в JVM Spec, самое первое отличие в том, что
invokevirtualпроверяет доступность метода, во время просмотра, в то время какinvokeinterfaceнет.
Comments