2010-12-12 55 views
36

C++有多重继承。在汇编层面实现多重继承可能会非常复杂,但是关于如何正常完成(vtables,pointer fixups,thunk等),还有很好的在线方式。java接口如何在内部实现? (vtables?)

Java没有多个实现继承,但它确实有多个接口继承,所以我不认为每个类都有一个单独的vtable可以实现它。 java如何在内部实现接口?

我意识到,与C++相反,Java是Jit编译的,因此不同的代码段可能会进行不同的优化,而不同的JVM可能会做不同的事情。那么,是否存在许多JVM遵循的一般策略,或者是否有人知道特定JVM中的实现?

此外,JVM通常是虚拟化和内联方法调用,在这种情况下根本不存在vtable或等效参数,所以询问实现虚拟/接口方法调用的实际汇编序列可能没有意义,但我认为大多数如果JVM还没有能够虚拟化所有的东西,那么JVM仍然会保留一些类的常规表示。这个假设是错误的吗?这种表示看起来像C++ vtable一样吗?如果是这样,接口是否有单独的vtables,并且它们如何与类vtables相关联?如果是这样,对象实例可以有多个vtable指针(类/接口vtables),就像C++中的对象实例一样?对同一个对象的类类型和接口类型的引用是否总是具有相同的二进制值,或者它们可以不同,就像它们需要指针修正的C++一样?

(供参考:this question询问有关CLR的类似的东西,而且似乎是一个很好的解释在this msdn article虽然可能现在已经过时了我一直没能找到适用于Java类似的话。)

编辑:

  • 我的意思是“工具”中的“如何GCC编译器实现整数加法/函数调用的/ etc”的意义,而不是在“Java类ArrayList中的意义实现List接口”。
  • 我知道这是如何工作在JVM字节码级别的,我想知道的是JVM在加载类文件和编译字节码后生成的代码和数据结构。
+2

您提到接口继承和实现继承。由于您需要定义搜索顺序,所以实现继承很困难。接口继承更简单。您只需拥有一张包含所有需要实施的方法签名的地图。不需要搜索顺序(因为没有附加任何实现)。那里没有订单。 – extraneon 2010-12-12 20:58:27

回答

25

HotSpot JVM的主要功能是inline caching。 这实际上并不意味着目标方法是内联的,而是意味着将假设 放入JIT代码中,以后每次调用虚函数或接口方法都将以 为目标实现(即呼叫站点是单态)。在这种情况下, 检查是否被编译到机器代码中,而不管该假设是否实际成立(即,目标对象的类型是否与上次相同),然后将控制 直接转移到目标方法 - with根本没有虚拟表格。如果断言失败,则可以尝试将其转换为megamorphic呼叫站点(即,具有多种可能的类型);如果这也失败了(或者它是第一次调用),使用vtables(用于虚拟方法)和itable(用于接口)执行常规的冗长查找。

编辑:本Hotspot Wiki对虚表和itable存根更多细节。在多态的情况下,它仍然将内联缓存版本放入调用站点。但是,代码实际上是一个在vtable中执行查找的存根,或者一个可用的存根。每个vtable偏移量(0,1,2,...)都有一个vtable存根。 Interface calls在给定的偏移量处查找可找到的(如果找到)之前,添加对它的数组的线性搜索。

+0

VirtualCalls和InterfaceCalls上的那些Hotspot Wiki页面似乎是我正在寻找的。尽管如此,仍然必须解决所有问题。 – JanKanis 2010-12-12 22:30:11

+1

Wiki已被移至https://wikis.oracle.com/display/HotSpotInternals/Home – 2012-04-27 17:30:39

+0

oracle wiki已冻结,我认为https://wiki.openjdk.java.net/display/HotSpot/Main是可更新信息结束。 – JanKanis 2014-12-04 10:36:16