Class MMethodInsn

  • All Implemented Interfaces:
    Serializable, xyz.cofe.collection.ImTree<ByteCode>, xyz.cofe.collection.ImTreeWalk<ByteCode>, ByteCode, MethodByteCode, MethodWriter

    public class MMethodInsn
    extends MAbstractBC
    implements MethodWriter
    This opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
    Зачем нужен invokeSpecial, когда существует invokeVirtual
    Ответ можно легко найти, если внимательно прочитать спецификацию Java VM: Разница между инструкциями invokespecial и invokevirtual заключается в том, что invokevirtual вызывает метод, основанный на классе объекта. Инструкция invokespecial используется для вызова методов инициализации экземпляра, а также частных методов и методов суперкласса текущего класса. Другими словами, invokespecial используется для вызова методов, не заботясь о динамической привязке, чтобы вызвать версию метода конкретного класса.
    В чем смысл invokeinterface?
    Каждый класс Java связан с таблицей виртуальных методов , содержащей "links" байт-кода каждого метода класса. Эта таблица наследуется от суперкласса определенного класса и расширяется в отношении новых методов подкласса. E.g.,
    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 и просто перезаписывает "link" из method2() , который она переопределяет.

    Таким образом, реализация JVM может оптимизировать вызов invokevirtual , помня, что BaseClass/method3() всегда будет третьей записью в таблице виртуальных методов любого объекта, на котором когда-либо будет вызван этот метод.

    С invokeinterface такая оптимизация невозможна. E.g.,

    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 должен будет проверить во время выполнения, существует ли метод в таблице, и потенциально вызвать исключение.

    See Also:
    Serialized Form
    • Constructor Detail

      • MMethodInsn

        public MMethodInsn()
        Конструктор по умолчанию
      • MMethodInsn

        public MMethodInsn​(int op,
                           String owner,
                           String name,
                           String descriptor,
                           boolean iface)
        Конструктор
        Parameters:
        op - the opcode of the type instruction to be visited. This opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
        код операции типа инструкции, которую нужно посетить. Этот код операции - INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC или INVOKEINTERFACE.
        owner - the internal name of the method's owner class (see Type.getInternalName()).
        внутреннее имя класса владельца метода (см. # getInternalName ()).
        name - the method's name.
        название метода.
        descriptor - the method's descriptor (see Type).
        дескриптор метода (см. Type).
        iface - if the method's owner class is an interface.
        если класс владельца метода является интерфейсом.
      • MMethodInsn

        public MMethodInsn​(MMethodInsn sample)
        Конструктор копирования
        Parameters:
        sample - образец
    • Method Detail

      • getOpcode

        public int getOpcode()
      • setOpcode

        public void setOpcode​(int opcode)
      • getOwner

        public String getOwner()
      • setOwner

        public void setOwner​(String owner)
      • getName

        public String getName()
      • setName

        public void setName​(String name)
      • getDescriptor

        public String getDescriptor()
      • setDescriptor

        public void setDescriptor​(String descriptor)
      • isIface

        public boolean isIface()
      • setIface

        public void setIface​(boolean iface)