java接口内部是如何实现的?(虚拟表?) [英] How are java interfaces implemented internally? (vtables?)

查看:18
本文介绍了java接口内部是如何实现的?(虚拟表?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C++ 具有多重继承.在程序集级别实现多重继承可能相当复杂,但网上有很好的描述这通常是如何完成的(虚拟表、指针修复、thunk 等).

C++ has multiple inheritance. The implementation of multiple inheritance at the assembly level can be quite complicated, but there are good descriptions online on how this is normally done (vtables, pointer fixups, thunks, etc).

Java 没有多重实现继承,但它有多重接口继承,所以我不认为每个类只有一个 vtable 的直接实现可以实现这一点.java内部是如何实现接口的?

Java doesn't have multiple implementation inheritance, but it does have multiple interface inheritance, so I don't think a straight forward implementation with a single vtable per class can implement that. How does java implement interfaces internally?

我意识到与 C++ 不同,Java 是由 Jit 编译的,因此不同的代码片段可能会以不同的方式进行优化,并且不同的 JVM 可能会以不同的方式做事.那么,是否有许多 JVM 遵循的一般策略,或者有人知道特定 JVM 中的实现吗?

I realize that contrary to C++, Java is Jit compiled, so different pieces of code might be optimized differently, and different JVMs might do things differently. So, is there some general strategy that many JVMs follow on this, or does anyone know the implementation in a specific JVM?

此外,JVM 经常去虚拟化和内联方法调用,在这种情况下根本不涉及 vtable 或等效项,因此询问实现虚拟/接口方法调用的实际汇编序列可能没有意义,但我假设大多数 JVM如果它们无法对所有内容进行去虚拟化,仍然保留一些类的一般表示以供使用.这个假设是错误的吗?这种表示看起来像 C++ 虚表吗?如果是这样,接口是否有单独的 vtables,它们如何与类 vtables 链接?如果是这样,对象实例是否可以像 C++ 中的对象实例那样具有多个 vtable 指针(指向类/接口 vtables)?对同一个对象的类类型和接口类型的引用是否总是具有相同的二进制值,或者它们是否可以像在需要指针修复的 C++ 中一样不同?

Also JVMs often devirtualize and inline method calls in which case there are no vtables or equivalent involved at all, so it might not make sense to ask about actual assembly sequences that implement virtual/interface method calls, but I assume that most JVMs still keep some kind of general representation of classes around to use if they haven't been able to devirtualize everything. Is this assumption wrong? Does this representation look in any way like a C++ vtable? If so do interfaces have separate vtables and how are these linked with class vtables? If so can object instances have multiple vtable pointers (to class/interface vtables) like object instances in C++ can? Do references of a class type and an interface type to the same object always have the same binary value or can these differ like in C++ where they require pointer fixups?

(供参考:这个问题提出了类似的问题关于 CLR,这篇 msdn 文章中似乎有很好的解释 虽然现在可能已经过时了.我还没有找到任何与 Java 类似的东西.)

(for reference: this question asks something similar about the CLR, and there appears to be a good explanation in this msdn article though that may be outdated by now. I haven't been able to find anything similar for Java.)

  • 我的意思是GCC 编译器如何实现整数加法/函数调用/等"意义上的实现",而不是Java 类 ArrayList 实现 List 接口"的意义上.
  • 我知道这在 JVM 字节码级别是如何工作的,我想知道的是 JVM 在完成加载类文件和编译字节码后生成什么样的代码和数据结构.

推荐答案

HotSpot JVM 的关键特性是 内联缓存.这实际上并不意味着目标方法是内联的,而是意味着假设被放入 JIT 代码中,以后对虚拟或接口方法的每次调用都将以此为目标完全相同的实现(即调用站点是单态的).在这种情况下,一个检查被编译成机器代码假设是否真的成立(即是否目标对象的类型与上次相同),然后转移控制直接到目标方法 - 根本不涉及虚拟表.如果断言失败,则可能会尝试将其转换为超态调用站点(即具有多种可能的类型);如果这也失败(或者如果它是第一次调用),则会执行常规的冗长查找,使用 vtables(用于虚拟方法)和 itables(用于接口).

The key feature of the HotSpot JVM is inline caching. This doesn't actually mean that the target method is inlined, but means that an assumption is put into the JIT code that every future call to the virtual or interface method will target the very same implementation (i.e. that the call site is monomorphic). In this case, a check is compiled into the machine code whether the assumption actually holds (i.e. whether the type of the target object is the same as it was last time), and then transfer control directly to the target method - with no virtual tables involved at all. If the assertion fails, an attempt may be made to convert this to a megamorphic call site (i.e. with multiple possible types); if this also fails (or if it is the first call), a regular long-winded lookup is performed, using vtables (for virtual methods) and itables (for interfaces).

编辑:热点Wiki 有更多关于 vtable 和 itable 存根的细节.在多态情况下,它仍然将内联缓存版本放入调用站点.但是,该代码实际上是在 vtable 或 itable 中执行查找的存根.每个 vtable 偏移量(0、1、2、...)都有一个 vtable 存根.接口调用在查看 itable (如果找到)在给定的偏移量.

Edit: The Hotspot Wiki has more details on the vtable and itable stubs. In the polymorphic case, it still puts an inline cache version into the call site. However, the code actually is a stub that performs a lookup in a vtable, or an itable. There is one vtable stub for each vtable offset (0, 1, 2, ...). Interface calls add a linear search over an array of itables before looking into the itable (if found) at the given offset.

这篇关于java接口内部是如何实现的?(虚拟表?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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