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

时间:2022-06-21 22:30:01

Quoting from http://sites.google.com/site/gson/gson-design-document:

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

Why are most classes in Gson marked as final?

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

While Gson provides a fairly extensible architecture by providing pluggable serializers and deserializers, Gson classes were not specifically designed to be extensible. Providing non-final classes would have allowed a user to legitimately extend Gson classes, and then expect that behavior to work in all subsequent revisions. We chose to limit such use-cases by marking classes as final, and waiting until a good use-case emerges to allow extensibility. Marking a class final also has a minor benefit of providing additional optimization opportunities to Java compiler and virtual machine.

虽然Gson通过提供可插拔的序列化器和反序列化器来提供相当可扩展的架构,但Gson类并不是专门设计为可扩展的。提供非最终类将允许用户合法地扩展Gson类,然后期望该行为在所有后续修订中工作。我们选择通过将类标记为final来限制这样的用例,并等到出现良好的用例以允许扩展性。标记类final也有一个很小的好处,即为Java编译器和虚拟机提供额外的优化机会。

Why is this the case? [If I would guess: of JVM knows class is final it does not maintain method override tables? Are there any other reasons?]

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

What is the benefit in performance?

性能有什么好处?

Does this applies to classes that are frequency instantiated (POJO?) or perhaps to class that are holders static methods (Utility classes) ?

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

Are methods defined as final also can theoretically improve performance?

定义为final的方法在理论上也可以提高性能吗?

Are there any implications?

有什么影响吗?

Thank you, Maxim.

谢谢你,马克西姆。

5 个解决方案

#1


37  

Virtual (overridden) methods generally are implemented via some sort of table (vtable) that is ultimately a function pointer. Each method call has the overhead of having to go through that pointer. When classes are marked final then all of the methods cannot be overridden and the use of a table is not needed anymore - this it is faster.

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

Some VMs (like HotSpot) may do things more intelligently and know when methods are/are not overridden and generate faster code as appropriate.

一些虚拟机(如HotSpot)可以更智能地执行操作,并且知道何时不覆盖方法并在适当时生成更快的代码。

Here is some more specific info on HotSpot. And some general info too.

以下是HotSpot的一些更具体的信息。还有一些一般信息。

#2


18  

An old, apparently no longer but still largely relevant, article on this from IBM developerWorks, which states:

IBM developerWorks上发表的一篇旧的,显然不再但仍然很重要的文章,其中指出:

The common perception is that declaring classes or methods final makes it easier for the compiler to inline method calls, but this perception is incorrect (or at the very least, greatly overstated).

常见的看法是,声明类或方法最终使编译器更容易内联方法调用,但这种看法是不正确的(或者至少,被夸大了)。

final classes and methods can be a significant inconvenience when programming -- they limit your options for reusing existing code and extending the functionality of existing classes. While sometimes a class is made final for a good reason, such as to enforce immutability, the benefits of using final should outweigh the inconvenience. Performance enhancement is almost always a bad reason to compromise good object-oriented design principles, and when the performance enhancement is small or nonexistent, this is a bad trade-off indeed.

最终的类和方法在编程时会带来很大的不便 - 它们限制了重用现有代码和扩展现有类功能的选择。虽然有时候一个班级是有充分理由的,例如强制执行不变性,但使用final的好处应该超过不便之处。性能增强几乎总是破坏良好的面向对象设计原则的坏理由,并且当性能增强很小或不存在时,这确实是一个糟糕的权衡。

Also see this related answer on another question. There's also the equivalent question for .Net, discussed here. SO discussion, "Are final methods inlined?" On a question titled "What optimizations are going to be useless tomorrow," this one appears on the list.

另请参阅另一个问题的相关答案。这里还讨论了.Net的等效问题。所以讨论,“内联的最终方法是什么?”在题为“明天哪些优化将毫无用处”的问题上,这一问题出现在名单上。

Here is someone trying to characterize the effect on HotSpot inlining from static and final classes.

这里有人试图描述静态和最终类对HotSpot内联的影响。

Note also that there is an entangling of the effects of final classes vs. final methods. You may get some performance benefit (again, I don't have a good reference) for final methods for sure, as it could cue the JIT to do inlining it couldn't otherwise do (or not so simply). You get the same effect when you mark the class final, which means that all the methods are suddenly final as well. Note that the Sun/Oracle folks claim that HotSpot can usually do this with or without the final keyword. Are there any additional effects from having the class itself final?

另请注意,最终类与最终方法的效果相互纠缠。对于最终方法,您可能会获得一些性能优势(同样,我没有一个很好的参考),因为它可以提示JIT进行内联,否则无法做到(或者不那么简单)。当你将类标记为final时,你会得到相同的效果,这意味着所有的方法也是最终的。请注意,Sun / Oracle人员声称HotSpot通常可以使用或不使用final关键字。让课程本身最终还有其他影响吗?

For reference, links to the JLS on final methods and final classes.

供参考,指向最终方法和最终类的JLS链接。

#3


1  

Not knowing the implementation of every particular JVM, I would theoretically say that if a JVM knows that a pointer to an object is a pointer to a type that is final, it can do non-virtual function calls (i.e., direct vs. indirect) to a member functions (i.e., no indirection through a function pointer), which may result in faster execution. This may also in turn lead to inlinining possibilities.

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

#4


1  

Marking classes as final allows further optimizations to be applied during the JIT stage.

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

If you are calling a virtual method on a non-final class, you don't know whether the proper implementation is the one defined in that class, or some sub-class that you don't know about.

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

However, if you have a reference to a final class, you know the specific implementation that is required.

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

Consider:

考虑:

A extends B
B extends C

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

In this case, the JIT can't know whether C's implementation of toString() or B's implementation of toString() will be called. However, if B is marked as final, it is impossible for any implementation other than B's to be the proper implementation

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

#5


0  

No difference, that's just speculation. The only situation where it has sense are classes like String, etc where jvm treat them differently.

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

#1


37  

Virtual (overridden) methods generally are implemented via some sort of table (vtable) that is ultimately a function pointer. Each method call has the overhead of having to go through that pointer. When classes are marked final then all of the methods cannot be overridden and the use of a table is not needed anymore - this it is faster.

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

Some VMs (like HotSpot) may do things more intelligently and know when methods are/are not overridden and generate faster code as appropriate.

一些虚拟机(如HotSpot)可以更智能地执行操作,并且知道何时不覆盖方法并在适当时生成更快的代码。

Here is some more specific info on HotSpot. And some general info too.

以下是HotSpot的一些更具体的信息。还有一些一般信息。

#2


18  

An old, apparently no longer but still largely relevant, article on this from IBM developerWorks, which states:

IBM developerWorks上发表的一篇旧的,显然不再但仍然很重要的文章,其中指出:

The common perception is that declaring classes or methods final makes it easier for the compiler to inline method calls, but this perception is incorrect (or at the very least, greatly overstated).

常见的看法是,声明类或方法最终使编译器更容易内联方法调用,但这种看法是不正确的(或者至少,被夸大了)。

final classes and methods can be a significant inconvenience when programming -- they limit your options for reusing existing code and extending the functionality of existing classes. While sometimes a class is made final for a good reason, such as to enforce immutability, the benefits of using final should outweigh the inconvenience. Performance enhancement is almost always a bad reason to compromise good object-oriented design principles, and when the performance enhancement is small or nonexistent, this is a bad trade-off indeed.

最终的类和方法在编程时会带来很大的不便 - 它们限制了重用现有代码和扩展现有类功能的选择。虽然有时候一个班级是有充分理由的,例如强制执行不变性,但使用final的好处应该超过不便之处。性能增强几乎总是破坏良好的面向对象设计原则的坏理由,并且当性能增强很小或不存在时,这确实是一个糟糕的权衡。

Also see this related answer on another question. There's also the equivalent question for .Net, discussed here. SO discussion, "Are final methods inlined?" On a question titled "What optimizations are going to be useless tomorrow," this one appears on the list.

另请参阅另一个问题的相关答案。这里还讨论了.Net的等效问题。所以讨论,“内联的最终方法是什么?”在题为“明天哪些优化将毫无用处”的问题上,这一问题出现在名单上。

Here is someone trying to characterize the effect on HotSpot inlining from static and final classes.

这里有人试图描述静态和最终类对HotSpot内联的影响。

Note also that there is an entangling of the effects of final classes vs. final methods. You may get some performance benefit (again, I don't have a good reference) for final methods for sure, as it could cue the JIT to do inlining it couldn't otherwise do (or not so simply). You get the same effect when you mark the class final, which means that all the methods are suddenly final as well. Note that the Sun/Oracle folks claim that HotSpot can usually do this with or without the final keyword. Are there any additional effects from having the class itself final?

另请注意,最终类与最终方法的效果相互纠缠。对于最终方法,您可能会获得一些性能优势(同样,我没有一个很好的参考),因为它可以提示JIT进行内联,否则无法做到(或者不那么简单)。当你将类标记为final时,你会得到相同的效果,这意味着所有的方法也是最终的。请注意,Sun / Oracle人员声称HotSpot通常可以使用或不使用final关键字。让课程本身最终还有其他影响吗?

For reference, links to the JLS on final methods and final classes.

供参考,指向最终方法和最终类的JLS链接。

#3


1  

Not knowing the implementation of every particular JVM, I would theoretically say that if a JVM knows that a pointer to an object is a pointer to a type that is final, it can do non-virtual function calls (i.e., direct vs. indirect) to a member functions (i.e., no indirection through a function pointer), which may result in faster execution. This may also in turn lead to inlinining possibilities.

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

#4


1  

Marking classes as final allows further optimizations to be applied during the JIT stage.

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

If you are calling a virtual method on a non-final class, you don't know whether the proper implementation is the one defined in that class, or some sub-class that you don't know about.

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

However, if you have a reference to a final class, you know the specific implementation that is required.

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

Consider:

考虑:

A extends B
B extends C

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

In this case, the JIT can't know whether C's implementation of toString() or B's implementation of toString() will be called. However, if B is marked as final, it is impossible for any implementation other than B's to be the proper implementation

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

#5


0  

No difference, that's just speculation. The only situation where it has sense are classes like String, etc where jvm treat them differently.

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