在Java中内联

时间:2009-07-21 13:11:55

标签: java jvm inlining inline-method

在C ++中,我可以声明一个“内联”方法,编译器可能会内联它。据我所知,Java中没有这样的关键字。

如果JVM决定这样做,内联是否已完成?我可以以某种方式影响这个决定吗?

8 个答案:

答案 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()”。

内联方法在呼叫站点提供以下好处:

  • 没有方法调用
  • 无动态调度
  • 可以对值进行常数折叠,例如。 “a.foo()+ 2”变为5,没有执行代码 运行时。

过去,程序员经常插入最终关键字正是出于这个原因。或者为了更好地促进内联并提高执行速度,他们会将许多较小的方法组合成一个更大的方法。但在许多方面,这种技术都破坏了编程语言中内置的模块化和可重用性的整个功能。

现代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内联函数)时,我发现它们之间没有性能改进。也许函数调用的开销已经非常低了。

注意:我使用了盒子模糊算法来评估性能。