在C ++中,我可以声明一个“内联”方法,编译器可能会内联它。据我所知,Java中没有这样的关键字。
如果JVM决定这样做,内联是否已完成?我可以以某种方式影响这个决定吗?
答案 0 :(得分:51)
其他几个答案表明,只有最终方法可以内联 - 这是不正确的,因为HotSpot足够智能,只要没有被覆盖,就可以内联非最终方法但。当加载一个覆盖该方法的类时,它可以撤消其优化。显然,使方法最终意味着永远不需要......
基本上让JVM完成它的工作 - 它可能比你在哪里进行内联更好。
您是否认为JVM没有做好工作?假设您正在使用HotSpot,您是否尝试使用服务器版本而不是客户端?这可能会产生巨大的差异。
答案 1 :(得分:6)
虽然java编译器可以内联(对于简短的早期绑定方法),但真实内联将由JIT编译器完成。 JIT(HotSpot)编译器甚至可以内联虚拟方法。 与之交互的最佳方式是编写简单而简洁的代码。 最有可能的是,使用Reflection的代码不允许内联。
希望有所帮助。
答案 2 :(得分:5)
'在C ++中,我可以声明一个方法“inline”,编译器会将它内联到 ...或者不是。编译器可以自由地使函数内联,也不会影响结果。它只是编译器的一个提示。
在Java中没有这样的东西,编译器(以及稍后执行优化时的VM)可以决定“内联”该方法。
请注意, final 方法更有可能被内联(编译器无法内联非最终方法,因为它们可能会在派生类中被覆盖)。使用现代VM,可以在运行时进行类似的优化。 VM将标记类型(因此它可以执行类型检查)并将内联代码。只有在检查失败时,它才会回到原始的未经优化的多态方法调用中。
答案 3 :(得分:4)
如果所讨论的方法是:
,则更有可能发生内联因为这些是JVM可以确定调用效果的唯一情况。
答案 4 :(得分:2)
class A {
final int foo() { return 3; }
}
鉴于此类,对foo()的任何调用都可以用常量“3”替换。任何Java1虚拟机都可以这样做,因为 final 关键字明确规定不可能有一个子类覆盖“int foo()”。
内联方法在呼叫站点提供以下好处:
过去,程序员经常插入最终关键字正是出于这个原因。或者为了更好地促进内联并提高执行速度,他们会将许多较小的方法组合成一个更大的方法。但在许多方面,这种技术都破坏了编程语言中内置的模块化和可重用性的整个功能。
现代JVM,就像Java HotSpot VM一样,可以在没有 final 的情况下内联类。关键字**。
(http://java.sun.com/developer/technicalArticles/Networking/HotSpot/inlining.html)
答案 5 :(得分:1)
阅读此内容行为。 http://www.javacoffeebreak.com/articles/thinkinginjava/comparingc++andjava.html
它说最终方法可以内联但不总是。
答案 6 :(得分:1)
是的,如果JVM决定这样做,它可以。影响的方法包括将方法设置为静态或最终。
当然,最重要的是该方法的结构需要内联友好。 Short有帮助,但最重要的是它只需要使用它的局部变量及其参数,没有字段,以及对同一类中其他方法的最小方法调用。
但是你不应该过早地进行这样的优化,实际上你可能会使事情变得更糟(因为你可能会使其他潜在的优化发生短路)。 JVM有时会意识到可以在没有这些提示的情况下内联方法。
答案 7 :(得分:1)
当比较正常函数和最终函数(据说是JVM内联函数)时,我发现它们之间没有性能改进。也许函数调用的开销已经非常低了。
注意:我使用了盒子模糊算法来评估性能。