39

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

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

4

8 回答 8

53

其他几个答案表明只能内联最终方法 - 这是不正确的,因为 HotSpot 足够聪明,只要它们还没有被覆盖,就能够内联非最终方法。当加载一个覆盖该方法的类时,它可以撤消其优化。显然,使方法最终意味着永远不需要......

基本上让 JVM 完成它的工作——它可能比你更擅长确定在哪里内联。

您是否有过确信 JVM 做得不好的情况?假设您使用的是 HotSpot,您是否尝试过使用服务器版本而不是客户端?这可以产生巨大的影响。

于 2009-07-21T13:19:15.880 回答
6

尽管 java 编译器可以内联(对于简短的早期绑定方法),但真正的内联将由 JIT 编译器完成。JIT (HotSpot) 编译器甚至能够内联虚拟方法。与之交互的最佳方式是编写简单明了的代码。最有可能的是,使用反射的代码不允许内联。

希望有帮助。

于 2009-07-21T13:20:59.997 回答
5

'在 C++ 中,我可以声明一个“内联”方法,编译器将内联它' ......或者不。编译器可以自由地使函数内联或不内联,你不能真正影响结果。这只是对编译器的提示。

在 Java 中没有这样的事情,编译器(以及稍后执行优化时的 VM)可以决定“内联”该方法。

请注意,最终方法被内联的机会更大(编译器不能内联非最终方法,因为它们可能在派生类中被覆盖)。使用现代 VM,可以在运行时进行类似的优化。VM 将标记类型(因此它可以执行类型检查)并将内联代码。只有当检查失败时,才会退回到原来未优化的多态方法调用。

于 2009-07-21T13:23:01.460 回答
4

如果所讨论的方法是以下情况,则更有可能发生内联:

  • 短的
  • 最终的
  • 不依赖于任何长的、非最终的方法

因为这些是 JVM 可以确定调用效果的唯一情况。

于 2009-07-21T13:15:44.090 回答
3
class A {
    final int foo() { return 3; }
}

给定这个类,任何对 foo() 的调用都可以用常量“3”代替。任何 Java1 虚拟机都可以做到这一点,因为final关键字明确规定不可能有一个覆盖“int foo()”的子类。

内联该方法在调用站点提供以下好处:

  • 没有方法调用
  • 没有动态调度
  • 可以恒定折叠值,例如。"a.foo()+2" 变为 5,运行时不执行任何代码

过去,程序员经常为此插入final关键字。或者为了更好地促进内联并提高执行速度,他们会将许多较小的方法组合成一个较大的方法。但在许多方面,这些技术破坏了编程语言内置的模块化和可重用性的整个设施。

现代 JVM,如 Java HotSpot VM,能够在没有final的情况下内联类。关键词**。

( http://java.sun.com/developer/technicalArticles/Networking/HotSpot/inlining.html )

于 2009-07-21T13:18:29.000 回答
2

阅读此内容以了解内联行为。 http://www.javacoffeebreak.com/articles/thinkinginjava/comparingc++andjava.html

它说最终方法可以内联,但并非总是如此。

于 2009-07-21T13:16:11.983 回答
1

是的,如果 JVM 决定这样做,它可以。影响的方法包括将方法设置为静态或最终的。

当然,最重要的是方法的结构需要内联友好。Short 有帮助,但最重要的是它只需要使用它的局部变量和它的参数,没有字段,以及对同一类中其他方法的最小方法调用。

但是,您不应该过早地进行此类优化,您实际上可能会使事情变得更糟(因为您可能会短路其他潜在的优化)。JVM 有时会意识到可以在没有这些提示的情况下内联方法。

于 2009-07-21T13:19:56.627 回答
1

在比较普通函数和最终函数(JVM 称为内联)时,我发现它们之间没有性能提升。也许函数调用的开销已经很低了。

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

于 2014-08-13T07:26:46.553 回答