Java是否通过一个接口优化方法调用,该接口将单个实现者标记为final?

Java是否通过一个接口优化方法调用,该接口将单个实现者标记为final?,java,performance,Java,Performance,如果我对一个类有一个引用并对其调用一个方法,并且该类或方法是最终的,那么我的理解是编译器或JVM将用一个更便宜的静态调度来代替动态调度,因为它可以准确地确定将调用哪个版本 但是,如果我引用了一个接口,而该接口当前只有一个实现者,并且该实现者是最终的,或者该实现者中的方法是最终的,JVM能否在运行时找到答案并优化这些调用呢?(在此处插入关于优化的Knuth引号。) 看 方法通常是内联的。这增加了编译器的“视野” 优化 静态、私有、最终和/或“特殊”调用很容易实现 内联 虚拟(和接口)调用通常降级

如果我对一个类有一个引用并对其调用一个方法,并且该类或方法是最终的,那么我的理解是编译器或JVM将用一个更便宜的静态调度来代替动态调度,因为它可以准确地确定将调用哪个版本

但是,如果我引用了一个接口,而该接口当前只有一个实现者,并且该实现者是最终的,或者该实现者中的方法是最终的,JVM能否在运行时找到答案并优化这些调用呢?

(在此处插入关于优化的Knuth引号。)

  • 方法通常是内联的。这增加了编译器的“视野” 优化
  • 静态、私有、最终和/或“特殊”调用很容易实现 内联
  • 虚拟(和接口)调用通常降级为“特殊” 调用,如果类层次结构 允许。已注册依赖项 以防进一步装载损坏 事情
  • 不平衡类型概要文件的虚拟(和接口)调用是 使用乐观签入进行编译 偏爱历史上常见的类型 (或两种类型)

这里有一些有趣的链接。

JIT编译器无法做到这一点,因为在运行时为接口创建代理是很常见的,所以JIT编译器永远无法确保不会有实现某个接口的动态代理。

AFAIK,JVM最多可以使用两种方法,这些方法不一定是最终的。如果方法很小并且经常调用,它可以做到这一点。如果代码调用三个或更多方法,则只调用最常用的方法

注1:JVM并不关心有多少实现,只关心实际调用了多少实现


注2:JVM可以内联编译时不存在的方法,只有运行时可用的代码才重要。

现在的Java虚拟机不再关心“final”关键字(仅用于类断言)。一切都被认为是最终的,除非加载的类重写了指定的函数,或者在接口的情况下提供了它的另一个实现

如果在JIT编译器已经编译了它认为是最终的东西之后,类在运行时被动态加载,那么这将导致代码的多次编译,但是获得的好处似乎是不费吹灰之力的


我没有这篇文章的链接,但我在几周前读过它(也许它只是用Java 7编写的,就像这样)。

+1。你在我能回答之前就回答了,而且你的链接比我能提供的更好。据我所知,当当前加载的类没有理由需要虚拟调用时,JVM肯定可以进行非虚拟调用。Java和.NET虚拟机的优点在于,当条件发生变化时,可以重新编译代码,例如加载的类现在要求方法是虚拟的。这允许更积极的优化。链接已断开。这是新的,新的链接也死了。这是上的新版本。事实上,JIT编译器可以使用某些假设进行优化,如果这些假设后来被发现无效,则可以取消优化。