![]() |
1
5
在Java的早期,有一个技术上的原因造成了这种差异。你知道“虚拟表”或“vtbl”是什么吗?基本上,一个简单的vtbl可以用于直接继承的方法,因此jvm只需查看两个指针就可以找到从抽象类继承的方法的代码——这相对来说比较快。但是,由于任何类都可以实现任意数量的接口,因此查找实现接口方法的代码将涉及跟踪指向由类实现的接口表的指针,然后搜索该表以查找实现该接口的vtbl,然后在表中查找方法指针。这显然需要做更多的工作,所以调用接口方法的速度过去要慢得多。 这些天,JVMs更聪明,而且大多数这种查找都是在动态编译期间完成的,所以运行时差异很小或者根本不存在。 |
![]() |
2
3
答案取决于实现细节,但在这种形式下,它是不正确的。事实上,作者已经试图通过稍微使用这个词来回避一个事实检查,以打开你从未观察到这种性能差异的可能性。 详细说明 this answer ,这种语句背后的思想是,一个普通类有一个由子类继承的可重写方法(也称为“vtable”)表,子类可以在末尾添加新方法,并替换它们重写的方法的表条目。因此,第一个解析只需要找到可以记住的表索引,因此后续调用只需要调用该索引处实际接收方类的方法。 由于接口可以由没有继承关系的不同类实现,因此实现方法可以位于这些类的不同表索引处。解决这个问题的一种方法是从接口表到实际的类表进行某种映射。假设这种双重分派导致了调用接口方法比普通方法慢的假设。
但是,像hotspot jvm这样的jvm不使用这种双重分派。它们像任何其他虚拟方法调用一样,解析针对实际接收方类的接口方法调用。只要接收者是同一类层次结构的一部分,例如,您可以调用
有些情况下,接口方法调用将在不相关类的不同实现中结束,例如,当调用
对于与性能相关的代码部分(也称为热点),jvm将执行运行时优化,从而使这种技术差异变得无关紧要。即使是普通虚拟方法调用的微小开销通常也会被消除,因为后续的优化严重依赖于积极内联目标方法代码的能力,以便能够使用调用方上下文及其已知的周围条件来优化被调用方代码。 |
![]() |
Sam · jvm如何优化循环代码? 6 年前 |
![]() |
pushpavanthar · 纱线中的调谐火花作业 6 年前 |
![]() |
Ashish K · 在Groovy中将字符串参数传递给对象方法参数 6 年前 |
![]() |
St.Antario · 在Java中侦听多个目录以创建文件 6 年前 |
![]() |
Bonsaisteak · 为什么年轻一代需要三个区域来收集垃圾? 6 年前 |