java - 用于超级方法的 Java vtable
问题描述
当我们有两个类时:
class Foo {
void foo() {
System.out.println("foo");
}
}
和:
class Bar extends Foo{
void bar() {
System.out.println("bar");
}
}
Bar clazz 对象是否在 vtable 中存储对 foo() 和 bar() 方法的引用,或者仅在 Bar 的 vtable 中引用 bar() 方法并访问 foo() 方法 jvm 访问 Bar clazz 对象,然后 Foo clazz 对象,然后在其 vtable 中找到 foo() 方法?是更像这样: 还是那样: 或者这可能没有在规范中描述并且可以依赖于 JVM 实现?
解决方案
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
------------------
这样的布局保证Foo
类的所有后代都将引用foo
vtable 中相同索引处的方法。这允许进行足够快的虚拟调用,即即使对于超态方法也可以在恒定时间内进行。
推荐阅读
- npm - 在已发布的 NPM 包中使用 styled-jsx 会给出警告:收到非布尔属性 `jsx` 的`true`
- java - Spring boot h2自动配置不起作用
- visual-studio - Visual Studio 不会打开 Safari 进行调试
- javascript - 如何使用 Windows 脚本设置手刹默认预设
- php - 检查 SQL Server 2017 中是否存在 $tablename,如果不存在则创建 TABLE $tablename
- javascript - 根据时间插值变化的值 (glsl)
- unity3d - 我可以为 Unity 网格设置两组顶点颜色吗?
- flutter - 如何在 PageView 中的小部件之间共享数据?
- swift - SwiftUI:删除行时使用 Array/Index 的 ForEach 崩溃
- kubernetes - Kubernetes集群中的DNS解决问题