为什么有 4 个单独的字节码来执行静态/虚拟/接口/特殊方法,而一个就足够了?
由于每个方法调用都包含目标方法签名,在我看来,类验证步骤可以通过分析目标来判断其是否调用静态、虚拟等并执行正确的操作?
使用 4 字节代码是否浪费 3 字节代码,或者如果使用 javap 转储类文件,这仅仅是自记录?
Since each method call includes the target method signature it seems to me that the class verifying step could tell by analysing the target whether its invoking a static, virtual etc and do the right thing ?
Is having 4 byte codes a waste of 3 byte codes or is this merely self documenting if one dumps a class file using javap ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果您谈论的是
invokeinterface
、invokespecial
、invokestatic
和invokevirtual
,那么有 它们之间的差异。首先是对堆栈的影响。If you're talking about
invokeinterface
,invokespecial
,invokestatic
, andinvokevirtual
, there are differences between them. The effects on the stack for a start.假设您只有虚拟和静态的调用操作码。让我们假设在编译时你
在某个地方用伪字节码调用了这个静态
现在让我们假设有人在运行时使用另一个 Test 类
在这种情况下
jmp Test.test(T)V
仍然有效。问题是它会弄乱堆栈。两个不同的操作码允许捕获这个问题的链接时间。Let's assume you have only invoke opcode for both virtual and static. Let's assume in compile time you have
and somewhere a call to this static with pseudo bytecode
Now let's assume someone uses another Test class in runtime
In this case
jmp Test.test(T)V
is still valid. The problem is that it will mess up the stack. Two different opcodes allow to catch this problem link time.这原本是可能的。然而,每次解释其中一条指令时都会增加额外的成本。因此,性能会因很少的优势而受到损害。
有人认为,单独的指令可以通过减少混淆虚拟机的机会来提高安全性。不确定我是否相信这一点。
This would have been possible. However, it would add extra cost every time one of the instructions is interpreted. So performance would be harmed for very little advantage.
It has been argued that separate instructions improve security, by reducing the chances of confusing the VM. Not sure I'm convinced by that.
您需要此操作码,因为在布置方法的字节码引用时,它们仅包含对常量池中条目的符号引用。要解析这些引用,您需要知道需要解析哪种类型:例如,invokespecial和invokevirtual之间的区别是静态绑定与动态绑定。对于invokespecial,您解析引用的类型,而不是对象的类。如果编译器不放入特殊的操作码来区分方法,则无法收集此信息。在java中,代码通常是动态链接的,这就是强制这些操作码的原因。
you need this opcodes because at the time the bytecode references for methods are laid out, they only contain symbolic references to entries in the constant pool. To resolve these references, you need to know on which type you need to resolve: for example, the difference between invokespecial and invokevirtual is static vs dynamic binding . For invokespecial you resolve on the type of the reference, not the class of the object. This information cannot be gleaned without the compiler putting in a special opcode to distinguish the methods. In java the code is typically linked dynamically, which is what forces these opcodes.
至少
invokespecial
需要是一个单独的指令,因为 java 允许显式调用重写方法的超级实现:Sub
中的调用必须是invokespecial< /code> 因为否则它只会调用自身并耗尽堆栈。
At least
invokespecial
is needed to be a separate instruction since java allows explicitly calling the super implementation of an overridden method:The call in
Sub
has to be aninvokespecial
since it would otherwise just call itself and run out of stack.我认为这场争论是不必要的,因为 java 有这样的设计决定。不确定,但您可能想再看一下他们所说的用户定义的数据端点:调用动态
I think This debate was unnneccesary as java have this design decision. Not sure but you might want to look at one more What they call user defined data endpoints : invokedynamic