在这篇文章中,我惊讶地读到:
我一直认为拥有
方法意味着编译器将使用final
而不是invokespecial
来编译对其的所有调用,以“虚拟化”方法调用,因为它在编译时已经确定在哪里转移执行。在编译时执行此操作似乎是一个微不足道的优化,而将其留给 JIT 则要复杂得多。但不,编译器不会这样做。这样做甚至不合法!invokevirtual
在编译时执行此操作似乎是一个微不足道的优化,因为它在编译时已经确定将执行转移到哪里。 没有发生这种情况的原因是什么?
贴出EJP在评论中指出的答案:
Java 有一个单独的编译模型,因此它禁止跨文件优化(有一个值得注意的例外,编译时常量内联)。如果您将方法更改为非最终方法,并且不重新编译客户端怎么办?如果您进行运行时字节码替换(搜索“instrumentation”)会怎样?
旁注:作为工程师,您的期望应该是工具的功能。这不是 C++。在你能买得起解释器的地方,字节码优化是不成熟的优化。
保持你的思维面向对象。你要求编译器去做,让它在幕后决定最好的;如果 20 岁的编译器不这样做,那么它可能并不重要。 -O 有详细记录(至少在 Oracle 的 JDK 上),它只是将私有方法和静态方法内联到声明它们的文件中。