运行时多态性决策

Meh*_*öse 8 java polymorphism jvm compiler-optimization

我在某处读过运行时多态性是langugages中动态类型的结果.通过检查下面的代码,我们可以看到运行时多态的一个明确的例子.

class A{
    do(){}
}
class B extends A{
    do(){}
}
...
A ex = new B();
ex.do();
Run Code Online (Sandbox Code Playgroud)

由于存在超类类型引用,编译器无法确定实际引用哪个类型引用并在运行时绑定方法.但是下面的用法与相同的类定义有什么关系呢?

我的第一个问题是下面的例子;

class A{
    do(){}
}
class B extends A{
  //no overriding
}
...
A ex = new B();
ex.do();
Run Code Online (Sandbox Code Playgroud)

层次结构中只有一个版本的方法do().系统是否仍在等待运行时绑定方法?还是在编译时绑定?

我的第二个问题是下面的例子;

class A{
    do(){}
}
class B extends A{
  do(){}
}
...
B ex = new B();
ex.do();
Run Code Online (Sandbox Code Playgroud)

现在有子类(继承链中最低)类型引用.它会在运行时绑定吗?

wer*_*ero 5

编译时,非静态方法的调用javac将始终使用invokevirtual指令,因此编译时不会进行优化。

但由于方法调用的去虚拟化是一项重要的优化(保存 vtable 查找,可能内联方法),因此运行时(热点等)将在可能的情况下尝试应用它,因为代码分析。

因此,在您的第二个示例(第三个代码块)中,运行时可能会认识到它可以将虚拟调用替换为对since的A.do调用,因为实际上a (在这种情况下,运行时应该很容易弄清楚)。B.doex B

对于您的第一个示例(第二个代码块),还有另一种优化技术。运行时首先看到 class A。的任何调用A.do现在都编译为静态调用,就好像不存在覆盖 的派生类一样A.do。如果稍后加载这样的类,运行时将回滚这种乐观假设并引入虚拟方法调用。