我正在阅读this article有关JVM如何调用方法的信息,我想我了解到了大部分。但是,我仍然无法理解invokeinterface
的需求。
以我的理解,一个类基本上有一个方法的虚拟表,当使用invokevirtual
或invokeinterface
调用方法时,将查询该虚拟表。
那么,在接口(interface)上定义的方法和在基类上定义的方法之间有什么区别?为什么使用不同的字节码?
description of the instructions也看起来非常相似。
这篇文章似乎声称,接口(interface)的方法表在每次调用方法时都可以具有“不同的偏移量”。我不明白的是,为什么一个接口(interface)根本没有方法表,因为没有对象可以将接口(interface)作为其实际类型。
我想念什么?
最佳答案
每个Java类都与一个虚拟方法表相关联,该表包含指向该类每个方法的字节码的“链接”。该表是从特定类的父类(super class)继承的,并针对子类的新方法进行了扩展。例如。,
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()
Note, how the virtual method table of NextClass
retains the order of entries of the table of BaseClass
and just overwrites the "link" of method2()
which it overrides.
An implementation of the JVM can thus optimize a call to invokevirtual
by remembering that BaseClass/method3()
will always be the third entry in the virtual method table of any object this method will ever be invoked on.
With invokeinterface
this optimization is not possible. 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() { }
}
该类层次结构产生虚拟方法表另一个类
1. BaseClass / method1()
2. NextClass / method2()
3. BaseClass / method3()
4. AnotherClass / method4()
5. MyInterface / ifaceMethod()
我的课
1. MyClass / method5()
2. MyInterface / ifaceMethod()
如您所见,
AnotherClass
在其第五个条目中包含接口(interface)的方法,而MyClass
在第二个条目中包含该接口(interface)的方法。为了在虚拟方法表中实际找到正确的条目,使用invokeinterface
的方法调用将始终必须搜索整个表,而没有机会获得invokevirtual
所做的优化风格。还有其他区别,例如
invokeinterface
可以与实际上未实现接口(interface)的对象引用一起使用。因此,invokeinterface
将必须在运行时检查表中是否存在方法,并可能引发异常。关于jvm - invokeinterface的意义是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1504633/