最终方法是内联的吗?
Java的final方法会自动内联吗?
很多书说可以,很多书说不!
Are Java final methods automatically inlined?
Many books says yes many books says no!!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
Java的final方法会自动内联吗?
很多书说可以,很多书说不!
Are Java final methods automatically inlined?
Many books says yes many books says no!!!
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(7)
方法的内联由 JIT 编译器执行,而不是 javac。
现代 JIT 编译器(包括 Hotspot)通常甚至可以内联非最终方法,并在必要时适当地“撤消”优化。他们基本上非常聪明。
简而言之:这完全取决于虚拟机。在我看来,你应该根据什么产生最干净的代码而不是性能来确定你的方法是否最终确定。我个人是“为继承而设计或禁止它”的粉丝,但这是一个不同的讨论:)
Inlining of methods is performed by the JIT compiler, not javac.
Modern JIT compilers (including Hotspot) can often inline even non-final methods, "undoing" the optimisation appropriately if necessary. They're basically scarily clever.
In short: it entirely depends on the VM. In my opinion, you should make your methods final or not based on what produces the cleanest code rather than performance. I'm personally a fan of "design for inheritance or prohibit it" but that's a different discussion :)
有趣的问题促使我进一步研究它。我发现了 2 条有趣的评论 -
内联是一个错误:
,更权威一点,来自 sun 白皮书,编写该方法可以保留虚拟,
这里有更多关于该机制的直接参考。
Interesting question, prompted me to look into it further. 2 interesting remarks I found -
inlining is a bug:
And, a bit more authoritatively, from a sun whitepaper, writing that methods can be left virtual,
Here's a more direct reference on the mechanism.
如果您的意思是“它们在编译期间内联吗”,那么不,它们不会。
但是,静态最终字段有时可以由编译器内联,例如基元和字符串。
If you mean "do they get inlined during compilation", then no, they won't.
However, static final fields sometimes can be inlined by the compiler, for example primitives and Strings.
final
更多的是向设计添加语义,而不是告诉编译器或虚拟机内联某些内容。现代虚拟机内联的内容远多于单独的最终方法,因此这不是使用final
或尝试过多预测运行时优化的好理由。final
is more about adding semantics to a design than to tell a compiler or VM to inline something. Modern VMs inline much more than final methods alone, so this is not a good reason to usefinal
or try to predict too much about runtime optimizations.我认为这取决于您运行的 JVM 的实现。当然,将方法设置为最终方法允许编译器选择进行此类实现调整。但它是否也可能取决于其他因素 - 例如,如果它是一个巨大的方法,等等......
I think that depends on which implementation of the JVM you are running on. Certainly, making a method final allows the compiler the option of making such an implementation tweak. But whether it does or not may also depend on other factors - e.g. what if its a huge method, etc.....
正如 Jon 所说,内联是由 JIT 编译器(在需要时)完成的,而不是在字节码生成级别完成的。另请注意,有时内联可能会导致性能下降,因为它可能会造成相同代码在 cpu l1 缓存中多次出现的情况,从而删除其他代码的空间。 L1 缓存未命中对性能的影响比跳转到缓存函数更大。
相反,常量(又名最终静态变量)被内联。
看这个检查
这个翻译过来是:
你可以看到静态函数InlineTest.add已经被
invokestatic
调用了多次As Jon said the inlining is done (when needed) by the JIT compiler not at bytecode generation level. Note also that sometimes inlining can result in a performance degradation because it could create a situation where the same code is present multiple times in the cpu l1 cache, removing space for other code. L1 cache misses can impact the performance more than a jump to a cached function.
Constants (aka final static var) are inlined instead.
See this to check
This is translated in:
You can see that static function InlineTest.add has been called multiple times with
invokestatic
Hotspot 决定是否内联是极其复杂的,依赖于过多的考虑,但我不认为该方法是否被标记为“final”是其中之一。原因是它已经知道该方法的多个实现是否已加载到VM中,因此知道是否允许这样的实现是无关紧要的。
无论如何,内联的只是非常小且简单的方法,甚至不是所有这些方法。
Hotspot's decision of whether to inline is incredibly complicated, dependent on a plethora of considerations, but I don't think whether the method is marked "final" is one of them. The reason is that it is already aware of whether multiple implementations of that method have been loaded in the VM, so it's irrelevant to also know whether such implementations are allowed.
In any case, it's only going to be very small and simple methods that get inlined, and not even all of those.