Java finals是否有助于编译器创建更有效的字节码? [重复]

问题描述 投票:45回答:4

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

final修饰符在Java中具有different consequences,具体取决于您将其应用于什么。我想知道的是additionally是否可以帮助编译器创建更有效的字节码。我想这个问题深入到JVM的工作方式,并且可能是特定于JVM的。

因此,就您的专业知识而言,以下任何一项对编译器有帮助吗,还是仅出于正常的Java原因而使用它们?

  • 最终班
  • 最终方法
  • 最终字段
  • 最终方法参数

谢谢!

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

java optimization micro-optimization
4个回答
63
投票

如果使用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 may

      会更改类初始化的顺序。)
  • 可以想象,将字段或局部参数声明为final可能会允许对JIT编译器进行较小的优化,否则将无法完成优化。但是,JIT编译器也可以将任何可以声明为final

    could

    的字段推断为有效的final。 (尚不清楚JIT编译器实际上是否会这样做,以及是否会影响所生成的本机代码。)
  • 但是,底线保持不变。您应该使用final来表达您的设计意图,而不是作为优化提示。


    1-该答案假设我们正在谈论具有良好JIT或AOT编译器的最新JVM。 1)最早的Sun Java实现根本没有JIT编译器。 2)早期的Android Java实现使用的编译器在优化方面做得很差。确实,早期的Android开发人员文档建议采用各种源代码级的微优化来弥补这一不足。此建议已被删除。

    该问题已经问了很多,通常的答案是:编译器可能会做一些优化(例如,内联常量是最终的静态字段),但是通常您不必理会,因为这些性能提升实际上可能不会引人注目。仅出于[正常] Java原因而使用final关键字(使字段或参数不变,防止子类化或方法的重写)。

    我建议您使用代码对其进行测试。在某些情况下,它可能与编译器有所不同,但是更可能对JIT产生影响。当涉及到微基准测试和微调整时,什么应该有所作为和实际上什么有所不同通常不是一回事,只有良好的测试才能确保。

    您遇到的另一个问题是,JVM一直在不断改进,而在此之前已不再起作用的一个大窍门。例如在Java 5.0中,Locksynchronized快得多,但是在Java 6中,差异很小,并且synchronized可以更快。

    通常,使您的代码简单,清晰且易于维护是一个好主意,这也将提高代码效率。

    使用final根本不会带来任何性能优势。由于性能原因,您必须求助于JNI。就是说,建议使用更好的JVM来自行优化字节码(例如:eclipse内置运行时比标准运行时更有效),并更加强调代码。

    11
    投票
    该问题已经问了很多,通常的答案是:编译器可能会做一些优化(例如,内联常量是最终的静态字段),但是通常您不必理会,因为这些性能提升实际上可能不会引人注目。仅出于[正常] Java原因而使用final关键字(使字段或参数不变,防止子类化或方法的重写)。

    6
    投票
    我建议您使用代码对其进行测试。在某些情况下,它可能与编译器有所不同,但是更可能对JIT产生影响。当涉及到微基准测试和微调整时,什么应该有所作为和实际上什么有所不同通常不是一回事,只有良好的测试才能确保。

    您遇到的另一个问题是,JVM一直在不断改进,而在此之前已不再起作用的一个大窍门。例如在Java 5.0中,Locksynchronized快得多,但是在Java 6中,差异很小,并且synchronized可以更快。


    -9
    投票
    使用final根本不会带来任何性能优势。由于性能原因,您必须求助于JNI。就是说,建议使用更好的JVM来自行优化字节码(例如:eclipse内置运行时比标准运行时更有效),并更加强调代码。
    © www.soinside.com 2019 - 2024. All rights reserved.