C ++有多重继承。在程序集级别实现多重继承可能非常复杂,但在线程上有很好的descriptions如何正常完成(vtables,指针修正,thunks等)。
Java没有多个实现继承,但它确实有多个接口继承,所以我不认为每个类有一个vtable的直接实现可以实现。 java如何在内部实现接口?
我意识到与C ++相反,Java是Jit编译的,因此不同的代码片段可能会有不同的优化,不同的JVM可能会以不同的方式做事。那么,是否存在许多JVM遵循的一般策略,或者有人知道特定JVM中的实现吗?
此外,JVM通常是虚拟化和内联方法调用,在这种情况下根本没有涉及vtable或等效项,因此询问实现虚拟/接口方法调用的实际汇编序列可能没有意义,但我认为大多数JVM如果他们无法虚拟化所有内容,仍会保留某种类的一般表示形式。这个假设是错的吗?这种表示形式是否像C ++ vtable一样?如果是这样,接口有单独的vtable,它们如何与类vtable链接?如果是这样,对象实例可以有多个vtable指针(对于类/接口vtable),就像C ++中的对象实例一样吗?对同一对象的类类型和接口类型的引用是否总是具有相同的二进制值,或者它们是否可以像C ++中那样需要指针修复?
(供参考:this question询问有关CLR的类似内容,this msdn article似乎有一个很好的解释,虽然现在可能已经过时了。我找不到任何东西类似于Java。)
修改
答案 0 :(得分:27)
HotSpot JVM的主要功能是inline caching。 这实际上并不意味着目标方法是内联的,而是意味着一个假设 将被放入JIT代码中,以后将对虚拟或接口方法的每个调用进行定位 相同的实现(即呼叫站点是单态的)。在这种情况下,一个 检查被编译成机器代码,无论假设是否实际成立(即是否 目标对象的类型与上次相同),然后转移控制 直接到目标方法 - 根本没有涉及虚拟表。如果断言失败,则可以尝试将其转换为变形呼叫站点(即具有多种可能类型);如果这也失败了(或者它是第一次调用),则使用vtables(对于虚方法)和itables(对于接口)执行常规的长卷查找。
编辑 :Hotspot Wiki包含有关vtable和itable存根的更多详细信息。在多态的情况下,它仍然将内联缓存版本放入调用站点。但是,代码实际上是一个在vtable或itable中执行查找的存根。每个vtable偏移量(0,1,2,...)都有一个vtable stub。 Interface calls在查看给定偏移处的itable(如果找到)之前,在itables数组上添加线性搜索。