Java finals是否有助于编译器创建更高效的字节码?

2022-08-31 20:55:42

可能的重复:
在Java中使用final关键字是否会提高性能?

最终的修饰符在java中具有不同的结果,具体取决于您将其应用于什么。我想知道的是,它是否可以帮助编译器创建更有效的字节码。我想这个问题深入探讨了JVM是如何工作的,并且可能是JVM特定的。

那么,以你的专业知识,以下任何一个对编译器有帮助,还是你只是为了正常的java原因而使用它们?

  • 期末课程
  • 最终方法
  • 最终字段
  • 最终方法参数

谢谢!

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


答案 1

如果使用,字节码的效率不会显著提高或降低,因为 Java 字节码编译器在优化方面通常很少。效率加成(如果有)将在 JIT 编译器1 生成的本机代码中。final

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

使用 还有其他语义后果:final

  • 将变量声明为可防止您意外更改它。(并向读者表达您的意图。final
  • 将方法声明为可防止在子类中重写。final
  • 将类声明为可完全防止子类化。final
  • 将字段声明为会阻止子类更改它。final
  • 将字段声明为对线程安全具有重要影响;请参阅 JLS 17.5final

在适当的情况下,这些都可以是好的。但是,很明显,它们通过创建子类来限制重用的选项。在决定是否使用 时,需要考虑这一点。final

因此,好的做法是(从广义上讲)表达您的设计意图,并实现您需要的其他语义效果。如果您仅用作优化提示,则不会取得多大成就。finalfinal


有几个例外情况可能会导致某些平台上的性能提高。final

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

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

但是,底线保持不变。您应该使用 来表达您的设计意图,而不是作为优化提示。final


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


答案 2

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


推荐