When we have two classes:
class Foo {
void foo() {
System.out.println("foo");
}
}
and:
class Bar extends Foo{
void bar() {
System.out.println("bar");
}
}
Does the Bar clazz object stores references to both foo() and bar() methods in vtable or there is just reference to bar() method in vtable of Bar and to access the foo() method jvm access the Bar clazz object, then Foo clazz object and then finds the foo() method in its vtable?
Is it more like this:
or that:
Or maybe this is not described in specification and can depend on JVM implementation?
JVM specification does not prescribe how to implement virtual method calls. It does not even refer to a notion of vtable. JVM implementation may choose this or another way as long as it behaves as expected.
As to HotSpot JVM, the reference implementation of Java SE virtual machine, it works like in your first picture, i.e. a single vtable of a class contains all its virtual methods including inherited.
------------------ ------------------
| 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
------------------
Such layout guarantees that all descendants of Foo
class will have the reference to foo
method at the same index in vtable. This allows to make virtual calls fast enough, i.e. in a constant time even for megamorphic methods.