为什么将类定义为final会改善JVM性能?

时间:2010-10-18 17:51:55

标签: java performance optimization jvm final

引自http://sites.google.com/site/gson/gson-design-document

  

为什么Gson中的大多数课程都标记为   最后?

     

虽然Gson提供了公平的   通过提供可扩展的体系结构   可插拔的序列化器和   反序列化者,Gson类没有   专门设计的   可扩展性。提供非决赛   类将允许用户   合法地扩展Gson类,并且   然后期望这种行为能够奏效   所有后续修订。我们选择了   通过标记来限制这种用例   作为最后的课程,等到一个   出现了良好的用例   可扩展性。将课程标记为最终   提供的好处也很小   额外的优化机会   到Java编译器和虚拟机。

为什么会这样? [如果我猜测:JVM知道类是最终的,它不维护方法覆盖表?还有其他原因吗?]

表现有什么好处?

这是适用于频率实例化的类(POJO?)还是适用于持有静态方法(实用类)的类?

定义为final的方法在理论上是否也能提高性能?

有任何影响吗?

谢谢你, 格言。

5 个答案:

答案 0 :(得分:37)

虚拟(重写)方法通常通过某种表(vtable)实现,该表最终是函数指针。每个方法调用都有必须通过该指针的开销。当类被标记为final时,所有方法都不能被覆盖,并且不再需要使用表 - 这样会更快。

某些虚拟机(如HotSpot)可以更智能地执行操作,并知道何时不覆盖方法并根据需要生成更快的代码。

Here是关于HotSpot的一些更具体的信息。还有一些general信息。

答案 1 :(得分:18)

旧的,显然不再是,但仍然主要相关的文章来自IBM developerWorks,其中声明:

  

普遍的看法是   最终声明类或方法   使编译器更容易   内联方法调用,但这   感知不正确(或在...   至少,被夸大了。)

     

最终的类和方法可以是一个   很不方便的时候   编程 - 它们限制了您的选择   用于重用现有代码和   扩展功能   现有的课程。虽然有时候   上课是有充分理由的,   比如强制执行不变性   使用final的好处应该是   超过了不便之处。   性能提升差不多   总是妥协妥协的坏理由   面向对象的设计原则,和   当性能提升时   小或不存在,这是一个坏的   实际上是权衡利弊。

另见related answer on another question。还有equivalent question for .Net, discussed here。 SO讨论,“Are final methods inlined?”在标题为“What optimizations are going to be useless tomorrow”的问题上,此列表出现在列表中。

以下是来自静态和最终类的HotSpot内联的someone trying to characterize the effect

另请注意,final类与final方法的效果相互纠缠。您可能获得final方法的一些性能优势(同样,我没有很好的参考),因为它可以提示JIT要做内联它本来不可能(或不那么简单)。标记类final时会得到相同的效果,这意味着所有方法也会突然变为最终方法。请注意,Sun / Oracle人员声称HotSpot通常可以使用或不使用final关键字来执行此操作。让班级本身final有任何额外的效果吗?

供参考,指向final methodsfinal classes上的JLS链接。

答案 2 :(得分:1)

不知道每个特定JVM的实现,我理论上会说如果JVM知道指向对象的指针是指向最终类型的指针,它可以执行非虚函数调用(即直接vs间接)到成员函数(即没有通过函数指针的间接),这可能导致更快的执行。这也可能反过来导致内在的可能性。

答案 3 :(得分:1)

将类标记为final允许在JIT阶段应用进一步的优化。

如果要在非final类上调用虚方法,则不知道正确的实现是否是该类中定义的实现,或者是您不了解的某个子类。

但是,如果您有对最终类的引用,则您知道所需的具体实现。

考虑:

A extends B
B extends C

B myInstance = null;
if(someCondition)
   myInstance = new B();
else
   myInstance = new C();
myInstance.toString();

在这种情况下,JIT无法知道是否将调用C的toString()实现或B的toString()实现。但是,如果B被标记为最终,则除了B之外的任何实现都不可能是正确的实现

答案 4 :(得分:0)

没有区别,这只是猜测。它有意义的唯一情况是像String这样的类,其中jvm以不同的方式对待它们。