用于超级方法的 Java vtable

swc*_*wch 2 java jvm dynamic-dispatch

当我们有两个类时:

class Foo {
    void foo() {
        System.out.println("foo");
    }
}
Run Code Online (Sandbox Code Playgroud)

和:

class Bar extends Foo{
    void bar() {
        System.out.println("bar");
    }
}
Run Code Online (Sandbox Code Playgroud)

Bar clazz 对象是否在 vtable 中存储对 foo() 和 bar() 方法的引用,或者仅在 Bar 的 vtable 中存储对 bar() 方法的引用并访问 foo() 方法 jvm 访问 Bar clazz 对象,然后访问 Foo clazz 对象,然后在其 vtable 中找到 foo() 方法?是不是更像这样: 在此输入图像描述 或者那个: 在此输入图像描述 或者也许这没有在规范中描述并且可以依赖于 JVM 实现?

apa*_*gin 5

JVM规范没有规定如何实现虚方法调用。它甚至没有提到vtable的概念。JVM 实现可以选择这种方式或另一种方式,只要它的行为符合预期。

至于HotSpot JVM,Java SE虚拟机的参考实现,它的工作原理就像你的第一张图片一样,即一个类的单个vtable包含它的所有虚拟方法,包括继承的方法。

     ------------------      ------------------ 
    | Foo.class vtable |    | Bar.class vtable |
    |------------------|    |------------------|
    | clone            |    | clone            | \
    | equals           |    | equals           | | java.lang.Object
    | hashCode         |    | hashCode         | / virtual methods
    | ...              |    | ...              |
    | foo              |    | foo              | } Foo virtual methods
     ------------------     | bar              | } Bar virtual methods
                             ------------------
Run Code Online (Sandbox Code Playgroud)

这种布局保证了Foo类的所有后代都将引用foovtable 中同一索引处的方法。这允许足够快地进行虚拟调用,即即使对于超态方法也可以在恒定时间内进行。

  • @swch 如果您使用“[Java HotSpot Performance Engine Architecture](https://www.oracle.com/technetwork/java/javase/tech/index-jsp-136373.html)”作为初始点。有大量链接可提供更多资源...如果您想与规范实际强制执行的内容进行比较,请参阅 [Java® 语言规范](https://docs.oracle.com/javase/specs/jls/ se11/html/index.html)和 [Java® 虚拟机规范](https://docs.oracle.com/javase/specs/jvms/se11/html/index.html)。 (2认同)