我正在分析 HotSpot 日志以获取我在 JITWatch 中为一段代码运行的基准,并注意到许多方法调用由于“无静态绑定(bind)”而没有被内联。这些似乎只发生在对默认接口(interface)方法的调用中。
我的问题是默认接口(interface)方法会阻止 JIT 编译器内联它们的调用吗?
interface A {
default double a() {
return Math.random();
}
}
interface B extends A {
default double b() {
return a();
}
}
class C implements B {
public double c() {
double c = 0;
for (int i = 0; i < 1_000_000; ++i) {
c += b();
}
return c;
}
public static void main(String[] args) {
System.out.println(new C().c());
}
}
在 JITWatch 中进一步检查后,似乎此问题与调用其他默认接口(interface)方法的默认接口(interface)方法有关。鉴于“无静态绑定(bind)”消息,这将更有意义。
最佳答案
Eugene 的示例表明可以内联默认方法。
事实上,我认为内联的标准应该与任何其他非静态方法相同。
在您的示例中,我认为内联应该是可能的,假设这是示例中涉及的所有代码。
但是,此处使用的特定 JIT 中的/可能存在其他限制。例如,一个调用另一个默认方法的默认方法可能是一种非常罕见的极端情况,以至于它被认为不值得支持。另一种可能的解释是 C1 编译器不进行深度单态调度分析/优化。
另一方面,这可能是过早的优化......除非您的性能分析已经确定了代码中的特定热点,其中内联可能会产生重大影响。通常,最好的策略是将其留给编译器。如果您对代码进行微优化以为给定的 Java 版本提供最佳性能,那么当您更改为较新的版本时,您很有可能需要重做工作。
关于java - JIT 编译器可以内联 Java 8 默认接口(interface)方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65473680/