有什么理由不将virtualvirtual和invokeinteface字节码指令合二为一吗? [英] Is there any reason for not invokevirtual and invokeinteface bytecode instruction into one?

查看:137
本文介绍了有什么理由不将virtualvirtual和invokeinteface字节码指令合二为一吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有必要使指令将非静态非构造方法的调用转换为两条不同的指令,而不是一条统一的指令(如invokeinstance)?它是否与某种随机的内部JVM机制有关,还是另一个可怕的遗留问题?

Is there any reason for making the instruction to invoke non-static non-constructor method into two distinct instruction instead of one unified instruction, like invokeinstance? Does it has anything to do with some random internal JVM mechanism or it's yet another horrific legacy issue?

我知道我们有invokespecial,因为调用构造函数需要名称ckecking,标记另一个构造函数已经执行,等等,以及invokestatic,因为我们不需要将 objectref 转储到新函数中堆栈框架.但是,它没有找到为什么Sun选择将可能的通用指令拆分为invokevirtualinvokeinterface的简单原因.如果不进行拆分,则ASM代码可能会简单得多,因为我们不必查看所有超级接口来查看这是否是一种接口方法,从而增强了代码的复杂性.

I know we have invokespecial because invoking constructor needs name ckecking, marking one other constructor has been executed, etc, and invokestatic because we don't need an objectref dumped into the new stack frame. It, however, doesn't has an easy-to-find reason why Sun opt to have the possible universal instruction spilted into invokevirtual and invokeinterface. Without spliting it, the ASM code could be a lot simpler since we don't have to look through the all superinterfaces to see if this is an interface method, building up the code conplexity.

推荐答案

Invokeinterface是不同的,因为接口仅在运行时进行类型检查.使用虚拟方法,您可以静态确定类型是定义方法的类的子类型.对于接口,在不知道值的运行时类型的情况下,无法确定是否知道该值是否具有实现该接口的类型.

Invokeinterface is different because interfaces are only type-checked at runtime. With a virtual method, you can statically determine that the type is a subtype of the class where the method is defined. For an interface, it is impossible to know for sure whether the value has a type that implements that interface without knowing the runtime type of the value.

考虑以下伪代码(请注意,Java中不允许使用此伪代码,但JVM允许使用等效的字节码)

Consider the following pseudocode (note that this isn't allowed in Java, but the bytecode equivalent is allowed by the JVM)

class A
class B extends A implements Foo

A a = new B()
a.fooMethod()

由于静态类型A不能实现Foo,而实际运行时类型B可以实现,因此无法静态地知道某个实现是否实现了Foo.

There is no way to statically know whether a implements Foo or not because the static type A doesn't implement Foo but the actual runtime type B does.

上面的示例将被Java编译器拒绝,但不会被JVM拒绝.您可能想知道为什么JVM不仅应用与编译器相同的规则.区别在于JVM没有有关局部变量的源级别类型信息.考虑下面的示例,在Java中是允许的.

The above example will be rejected by the Java compiler, but not the JVM. You might wonder why the JVM doesn't just apply the same rules as the compiler. The difference is that the JVM doesn't have source level type information about local variables. Consider the following example, which is allowed in Java.

class A
class B extends A implements Foo
class C extends A implements Foo

Foo x = null;
if (whatever) {
x = new B();
} else {
x = new C();
}
x.fooMethod();

JVM不知道x的预期类型(没有stackmaptables,直到稍后才引入),因此它推断x的类型为A,这没有实现Foo.因此,如果尝试静态检查接口作为验证时间,它将拒绝有效的Java代码!唯一可行的解​​决方案是不对接口进行类型检查.

The JVM doesn't know the intended type of x (without stackmaptables, which weren't introduced until much later), so it infers the type of x to be A, which doesn't implement Foo. Therefore, if it tried to statically check interfaces as verification time, it would reject valid Java code! The only feasible solution is to not typecheck interfaces.

为了安全地检查接口,JVM必须能够推断出诸如也实现Foo的A的子类"之类的类型,这显然为必须快速高效的事物增加了极大的复杂性.因此,设计师没有走这条路很有意义.

In order to safely check interfaces, the JVM would have to be able to infer types like "subclass of A which also implements Foo", which obviously adds an enormous amount of complexity to something which has to be fast and efficient. So it makes sense that the designers didn't go this route.

P.S. Invokespecial不仅适用于构造函数-还用于私有和超级方法调用.它最有可能最初是作为优化的独立指令,因为被调用的方法在加载时是已知的,而不是随目标的运行时类型而变化.实际上,它最初被称为invokenonvirtual.

P.S. Invokespecial isn't just for constructors - it's also used for private and super method calls. Most likely it was originally a separate instruction as an optimization, since the invoked method is known at load time instead of varying with the runtime type of the target. In fact, it was originally called invokenonvirtual.

这篇关于有什么理由不将virtualvirtual和invokeinteface字节码指令合二为一吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆