java Finals 是否有助于编译器创建更高效的字节码?
可能的重复:
在Java中使用final关键字会提高性能吗?< /a>
final 修饰符在以下情况下具有不同的后果 java 取决于什么你把它应用到。我想知道它是否可以帮助编译器创建更高效的字节码。我想这个问题深入到 JVM 如何工作,并且可能是 JVM 特定的。
那么,根据您的专业知识,以下任何内容是否对编译器有帮助,或者您仅出于正常的 java 原因才使用它们?
- Final 类
- Final 方法
- Final 字段
- Final 方法参数
谢谢!
编辑:感谢您的所有回答!请注意,正如 @Zohaib 所建议的,我的问题与
Possible Duplicate:
Does use of final keyword in Java improve the performance?
The final modifier has different consequences in java depending on what you apply it to. What I'm wondering is if additionally it might help the compiler create more efficient bytecode. I suppose the question goes deep into how the JVM work and might be JVM specific.
So, in your expertise, do any of the following help the compiler, or do you only use them for the normal java reasons?
- Final classes
- Final methods
- Final fields
- Final method arguments
Thanks!
EDIT: Thanks for all your answers! Please note that, as @Zohaib suggested, my question is a duplicate of this. I didn't search well enough before posting. I'm not deleting it because you guys made good contributions, but the answers could be merged. I'll let the "vote for close" system decide unless told otherwise.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果使用
final
,字节码的效率不会显着提高或降低,因为 Java 字节码编译器通常很少进行优化。效率加成(如果有)将体现在 JIT 编译器1生成的本机代码中。理论上,使用
final
可以为 JIT 编译器提供提示,帮助其优化。实际上,最近的 HotSpot JIT 编译器可以通过忽略您的提示来做得更好。例如,现代 JIT 编译器通常会执行全局分析,以查明给定方法调用是否是对应用程序当前加载的类上下文中的叶方法的调用。此分析比您的final
提示更准确,运行时甚至可以检测何时加载使分析无效的新类...并为受影响的代码重做分析和本机代码生成。使用
final
还有其他语义后果:final
可以防止您意外更改它。 (并向读者表达您的意图。)final
可以防止在子类中重写。final
可以完全防止子类化。final
会阻止子类更改它。final
对于线程安全具有重要影响;请参阅 JLS 17.5。在适当的情况下,这些都可以是好的。然而,很明显,它们通过创建子类限制了您重用的选择。在决定是否使用
final
时需要考虑这一点。因此,好的做法是使用
final
来(广义上)表达您的设计意图,并实现您需要的其他语义效果。如果您仅使用final
作为优化提示,您将不会取得多大成果。在一些例外情况下,
final
可能在某些平台上带来较小的性能改进。在某些情况下,将字段声明为
final
会改变字节码编译器处理它的方式。我在上面举了一个例子。另一种是“常量变量”情况(JLS 4.12.4),其中static final
字段的值将由字节码编译器内联到当前类和其他类中,并且这可能会影响观察到的代码行为。 (例如,引用常量变量不会触发类初始化。因此,添加final
可能会更改类初始化的顺序。)可以想象,将字段或本地参数声明为
final
可能会允许进行较小的 JIT 编译器优化,而这在其他情况下是无法完成的。但是,任何可以声明为 Final 的字段也可以被 JIT 编译器推断为有效的 Final。 (只是不清楚 JIT 编译器实际上是这样做的,以及这是否会影响生成的本机代码。)但是底线保持不变。您应该使用
final
来表达您的设计意图,而不是作为优化提示。1 - 此答案假设我们正在讨论具有良好 JIT 或 AOT 编译器的最新 JVM。 1) 最早的 Sun Java 实现根本没有 JIT 编译器。 2) 早期的 Android Java 实现的编译器在优化方面做得很差。事实上,早期的 Android 开发者文档建议进行各种源代码级微优化来进行补偿。此建议已被删除。
The bytecodes are not significantly more or less efficient if you use
final
because Java bytecode compilers typically do little in the way optimization. The efficiency bonus (if any) will be in the native code produced by the JIT compiler1.In theory, using the
final
provides a hint to the JIT compiler that should help it optimize. In practice, recent HotSpot JIT compilers can do a better job by ignoring your hints. For instance, a modern JIT compiler typically performs a global analysis to find out if a given method call is a call to a leaf method in the context of the application's currently loaded classes. This analysis is more accurate than yourfinal
hints can be, and the runtime can even detect when a new class is loaded that invalidates the analysis ... and redo the analysis and native code generation for the affected code.There are other semantic consequences for use of
final
:final
stops you from accidentally changing it. (And expresses your intention to the reader.)final
prevents overriding in a subclass.final
prevents subclassing entirely.final
stops a subclass from changing it.final
has important consequences for thread-safety; see JLS 17.5.In the right circumstances, these can all be good. However, it is clear that they limit your options for reuse by creating subclasses. This needs to be considered when deciding whether or not to use
final
.So good practice is to use
final
to (broadly speaking) express your design intentions, and to achieve other semantic effects that you require. If you usefinal
solely as an optimization hint, you won't achieve much.There are a couple of exceptions where
final
could lead to small performance improvements on some platforms.Under certain circumstances, declaring a field as
final
changes the way that the bytecode compiler deals with it. I've given one example above. Another is the "constant variable" case (JLS 4.12.4) where astatic final
field's value will be inlined by the bytecode compiler both in the current classes, and in other classes, and this may affect the observed behavior of code. (For example, referring to a constant variable will NOT trigger class initialization. Hence, the addition of afinal
may change the order of class initialization.)It is conceivable that declaring a field or local parameter as
final
may allow minor JIT compiler optimization that wouldn't otherwise be done. However, any field that can be declared as final could also be inferred to be effectively final by the JIT compiler. (It is just not clear that the JIT compiler actually does this, and whether that affects the generated native code.)However the bottom line remains the same. You should use
final
to express your design intentions, not as an optimization hint.1 - This answer assumes that we are talking about a recent JVM with a good JIT or AOT compiler. 1) The earliest Sun Java implementations didn't have a JIT compiler at all. 2) Early Android Java implementations had compilers which did a poor job of optimizing. Indeed the early Android developer documentation advised various source-level micro-optimizations to compensate. This advice has since been removed.
这个问题已经被问了很多次,答案通常是:编译器可能会做一些优化(例如,内联常量是最终静态字段),但通常您不应该为此烦恼,因为这些性能提升实际上可能并不明显。只需使用
final
关键字来实现“正常”Java 原因(使字段或参数不可变、防止子类化或重写方法)。That question has already been asked quite a lot and the answer generally is: the compiler might do some optimisations (e.g. inline constants which are final static fields) but generally you shouldn't bother with this, since those performance gains might actually not be noticable. Just use the
final
keyword for the "normal" Java reasons (make fields or parameters immutable, prevent subclassing or overriding of methods).我建议你用你的代码进行测试。在某些情况下,它可能会对编译器产生影响,但更有可能对 JIT 产生影响。当涉及到微基准和微调整时,应该产生影响的因素和实际产生影响的因素通常不是同一件事,只有良好的测试才能确定。
您遇到的另一个问题是 JVM 一直在改进,以前产生很大影响的技巧可能不再适用。例如,在 Java 5.0 中,
Lock
比synchronized
快得多,但是在 Java 6 中,差异要小得多,并且synchronized
可以更快。一般来说,让你的代码简单、清晰、易于维护是一个好主意,这也会带来高效的代码。
I suggest you test it with your code. It can make a different to the compiler in some cases however it is more likely to make a difference to the JIT. When it comes to micro-benchmarks and micro-tuning what should make a difference and what actually makes a difference is often not the same thing and only good testing is the way to be sure.
Another problem you have is that the JVM is improving all the time and a trick which made a big difference before may no longer apply. e.g. in Java 5.0
Lock
was much faster thansynchronized
however in Java 6 the difference is much smaller andsynchronized
can be faster.In generally, its a good idea to make your code simple, clear and easily maintainable and this will also result in efficient code.