java决赛有助于编译器创建更高效​​的字节码吗?

时间:2011-12-02 09:45:45

标签: java optimization micro-optimization

  

可能重复:
  Does use of final keyword in Java improve the performance?

final 修饰符在java中有different consequences,具体取决于您应用它的内容。我想知道的是,如果另外它可能有助于编译器创建更高效​​的字节码。我想这个问题深入探讨了JVM的工作方式以及JVM的特定性。

因此,根据您的专业知识,请执行以下任何操作以帮助编译器,或者您是否仅出于正常的java原因使用它们?

  • 最后的课程
  • 最终方法
  • 最终字段
  • 最终方法参数

谢谢!

编辑:谢谢你的所有答案!请注意,正如@Zohaib建议的那样,我的问题与this重复。在发布之前我搜索得不够好。我不是删除它,因为你们做出了很好的贡献,但答案可以合并。除非另有说明,否则我会让“投票结束”系统决定。

4 个答案:

答案 0 :(得分:57)

如果使用final,字节码的效率可能没那么高效或低效,因为Java字节码编译器通常在优化方式上做的很少。效率奖励(如果有的话)将在JIT编译器生成的本机代码中。

理论上,使用final为JIT编译器提供了一个有助于优化的提示。在实践中,最近的HotSpot JIT编译器可以通过忽略您的提示来做得更好。例如,现代JIT编译器通常执行全局分析以查明给定方法调用是否是在应用程序当前加载的类的上下文中对叶方法的调用。此分析比您的final提示更准确,运行时甚至可以检测何时加载新类使分析无效...并重新生成受影响代码的分析和本机代码生成。

因此,最佳做法是使用final(广泛地说)来表达您的设计意图,并实现您需要的其他语义效果。 (例如,使用final修饰符可以在实现线程安全的不可变类型中发挥重要作用;请参阅JLS 17.5)如果使用final作为优化提示,则无法实现,你将使你的代码更难修改和扩展。

<强>更新

这有几个例外(如下所述):

  • 在某些情况下,将字段声明为final会改变字节码编译器处理它的方式。我上面举了一个例子。另一个是“常量变量”情况(JLS 4.12.4),其中static final字段的值将由当前类和其他类中的字节码编译器进行内联,并且这可能会影响观察到的代码行为。 (例如,引用常量变量不会触发类初始化。因此,添加final 可能会更改类初始化的顺序。)

  • 可以想象,将字段或本地参数声明为final可能允许进行小的JIT编译器优化,否则将无法完成。但是,任何可以声明为final 的字段也可以被JIT编译器推断为有效的最终字段。 (目前尚不清楚JIT编译器是否实际执行此操作,以及是否会影响生成的本机代码。)

但是,我以前的建议适用。使用final来表达您的设计意图,而不是优化提示。

答案 1 :(得分:10)

这个问题已经被问了很多,答案一般是:编译器可能会做一些优化(例如内联常量,这是最终的静态字段)但通常你不应该为此烦恼,因为这些性能增益可能实际上不值得注意。只需将final关键字用于“正常”Java原因(使字段或参数不可变,防止子类化或覆盖方法)。

答案 2 :(得分:6)

我建议你用你的代码进行测试。在某些情况下,它可以使编译器与众不同,但它更有可能对JIT产生影响。当涉及到微观基准和微调时,哪些应该有所作为,哪些实际上有所不同往往不是一回事,只有好的测试才是确定的方法。

你遇到的另一个问题是JVM一直在不断改进,而且在之前可能不再适用的技巧也有很大的不同。例如在Java 5.0中,Locksynchronized快得多,但在Java 6中,差异要小得多,synchronized可以更快。

通常,最好使代码简单,清晰且易于维护,这也会产生高效的代码。

答案 3 :(得分:-8)

使用final可以完全没有性能优势。出于性能原因,您必须求助于JNI。也就是说,建议使用更好的JVM来自己优化字节码(例如:eclipse内置运行时比标准内存更有效)并且更加重视代码。