在Java中使用final会改进垃圾收集吗?

时间:2021-05-07 03:50:00

Today my colleagues and me have a discussion about the usage of the final keyword in Java to improve the garbage collection.

今天我的同事和我讨论了在Java中使用final关键字来改进垃圾收集。

For example, if you write a method like:

例如,如果您编写一个方法:

public Double doCalc(final Double value)
{
   final Double maxWeight = 1000.0;
   final Double totalWeight = maxWeight * value;
   return totalWeight;  
}

Declaring the variables in the method final would help the garbage collection to clean up the memory from the unused variables in the method after the method exits.

在方法final中声明变量将有助于垃圾收集在方法退出后清理方法中未使用的变量的内存。

Is this true?

这是真的吗?

14 个解决方案

#1


80  

Here's a slightly different example, one with final reference-type fields rather than final value-type local variables:

这里有一个稍微不同的例子,一个具有最终引用类型字段而不是最终值类型局部变量的例子:

public class MyClass {

   public final MyOtherObject obj;

}

Every time you create an instance of MyClass, you'll be creating an outgoing reference to a MyOtherObject instance, and the GC will have to follow that link to look for live objects.

每次创建MyOtherObject类的实例时,都将创建一个对MyOtherObject实例的传出引用,GC必须遵循该链接来查找活动对象。

The JVM uses a mark-sweep GC algorithm, which has to examine all the live refereces in the GC "root" locations (like all the objects in the current call stack). Each live object is "marked" as being alive, and any object referred to by a live object is also marked as being alive.

JVM使用标记-清除GC算法,它必须检查GC“根”位置中的所有活动引用(就像当前调用堆栈中的所有对象一样)。每个活动对象都被“标记”为“活着”,任何被活动对象引用的对象也被标记为“活着”。

After the completion of the mark phase, the GC sweeps through the heap, freeing memory for all unmarked objects (and compacting the memory for the remaining live objects).

标记阶段完成后,GC遍历堆,释放所有未标记对象的内存(并压缩其余活动对象的内存)。

Also, it's important to recognize that the Java heap memory is partitioned into a "young generation" and an "old generation". All objects are initially allocated in the young generation (sometimes referred to as "the nursery"). Since most objects are short-lived, the GC is more aggressive about freeing recent garbage from the young generation. If an object survives a collection cycle of the young generation, it gets moved into the old generation (sometimes referred to as the "tenured generation"), which is processed less frequently.

此外,重要的是要认识到Java堆内存被划分为“年轻一代”和“老一代”。所有对象最初都分配给年轻一代(有时称为“托儿所”)。由于大多数对象都是短期的,所以GC在从年轻一代中释放最近的垃圾时更加积极。如果一个对象在年轻一代的集合周期中存活下来,那么它将被转移到老一代(有时被称为“长期一代”)中,这一过程处理得更少。

So, off the top of my head, I'm going to say "no, the 'final' modifer doesn't help the GC reduce its workload".

因此,在我的脑海中,我会说“不,‘最终’修改器不能帮助GC减少它的工作负载”。

In my opinion, the best strategy for optimizing your memory-management in Java is to eliminate spurious references as quickly as possible. You could do that by assigning "null" to an object reference as soon as you're done using it.

在我看来,优化Java内存管理的最佳策略是尽可能快地消除虚假引用。您可以通过在使用对象引用时将“null”分配给对象引用来实现这一点。

Or, better yet, minimize the size of each declaration scope. For example, if you declare an object at the beginning of a 1000-line method, and if the object stays alive until the close of that method's scope (the last closing curly brace), then the object might stay alive for much longer that actually necessary.

或者,更好的是,最小化每个声明范围的大小。例如,如果您在一个1000行方法的开头声明一个对象,并且如果该对象在该方法的作用域(最后一个闭花括号)结束之前保持活动状态,那么该对象可能会在实际需要的时间内保持活动状态。

If you use small methods, with only a dozen or so lines of code, then the objects declared within that method will fall out of scope more quickly, and the GC will be able to do most of its work within the much-more-efficient young generation. You don't want objects being moved into the older generation unless absolutely necessary.

如果您使用的方法很小,只有十几行代码,那么该方法中声明的对象将更快地退出范围,GC将能够在效率更高的年轻一代中完成大部分工作。除非绝对必要,否则不希望对象被转移到老一代。

#2


36  

Declaring a local variable final will not affect garbage collection, it only means you can not modify the variable. Your example above should not compile as you are modifying the variable totalWeight which has been marked final. On the other hand, declaring a primitive (double instead of Double) final will allows that variable to be inlined into the calling code, so that could cause some memory and performance improvement. This is used when you have a number of public static final Strings in a class.

声明局部变量final不会影响垃圾收集,它只意味着不能修改该变量。上面的示例不应该编译,因为您正在修改已标记为final的变量totalWeight。另一方面,声明一个原语(double而不是double) final将允许将该变量内联到调用代码中,因此可能会导致一些内存和性能改进。当类中有许多公共静态最终字符串时,可以使用此方法。

In general, the compiler and runtime will optimize where it can. It is best to write the code appropriately and not try to be too tricky. Use final when you do not want the variable to be modified. Assume that any easy optimizations will be performed by the compiler, and if you are worried about performance or memory use, use a profiler to determine the real problem.

一般来说,编译器和运行时将在它能优化的地方进行优化。最好是适当地编写代码,而不要太复杂。当不希望修改变量时使用final。假设编译器将执行任何简单的优化,如果您担心性能或内存使用,请使用分析器来确定真正的问题。

#3


24  

No, it is emphatically not true.

不,这绝对不是真的。

Remember that final does not mean constant, it just means you can't change the reference.

记住,final不是指常数,它只是表示你不能改变引用。

final MyObject o = new MyObject();
o.setValue("foo"); // Works just fine
o = new MyObject(); // Doesn't work.

There may be some small optimisation based around the knowledge that the JVM will never have to modify the reference (such as not having check to see if it has changed) but it would be so minor as to not worry about.

基于JVM永远不需要修改引用的知识(比如不检查是否修改引用),可能会有一些小的优化,但是这些优化非常小,以至于不必担心。

Final should be thought of as useful meta-data to the developer and not as a compiler optimisation.

Final应该被视为对开发人员有用的元数据,而不是编译器优化。

#4


15  

Some points to clear up:

有几点需要澄清:

  • Nulling out reference should not help GC. If it did, it would indicate that your variables are over scoped. One exception is the case of object nepotism.

    取消引用不应该帮助GC。如果它这样做了,它将表明您的变量的作用域超出了范围。对象裙带关系是一个例外。

  • There is no on-stack allocation as of yet in Java.

    在Java中还没有堆栈分配。

  • Declaring a variable final means you can't (under normal conditions) assign a new value to that variable. Since final says nothing about scope, it doesn't say anything about it's effect on GC.

    声明变量final意味着您不能(在正常情况下)为该变量赋新值。因为final没有说明范围,它没有说明它对GC的影响。

#5


10  

Well, I don't know about the use of the "final" modifier in this case, or its effect on the GC.

我不知道在这种情况下如何使用“final”修饰符,或者它对GC的影响。

But I can tell you this: your use of Boxed values rather than primitives (e.g., Double instead of double) will allocate those objects on the heap rather than the stack, and will produce unnecessary garbage that the GC will have to clean up.

但是我可以告诉您:您使用装箱值而不是原语(例如,Double而不是Double)将在堆上而不是堆栈上分配这些对象,并将产生GC必须清理的不必要的垃圾。

I only use boxed primitives when required by an existing API, or when I need nullable primatives.

我只在现有API需要的时候使用封装的原语,或者在需要可空的原语的时候使用。

#6


5  

Final variables cannot be changed after initial assignment (enforced by the compiler).

在初始分配(由编译器执行)之后,不能更改最终变量。

This does not change the behaviour of the garbage collection as such. Only thing is that these variables cannot be nulled when not being used any more (which may help the garbage collection in memory tight situations).

这不会改变垃圾收集的行为。惟一的问题是,这些变量在没有被使用时不能被取消(这可能有助于在内存紧张的情况下收集垃圾)。

You should know that final allows the compiler to make assumptions about what to optimize. Inlining code and not including code known not to be reachable.

您应该知道,final允许编译器假设要优化什么。内联代码,不包括已知不可访问的代码。

final boolean debug = false;

......

if (debug) {
  System.out.println("DEBUG INFO!");
}

The println will not be included in the byte code.

将不会在字节代码中包含println。

#7


3  

GC acts on unreachable refs. This has nothing to do with "final", which is merely an assertion of one-time assignment. Is it possible that some VM's GC can make use of "final"? I don't see how or why.

GC作用于无法到达的裁判。这与“最终”没有关系,“最终”只是一次性分配的断言。是否有些VM的GC可以使用“final”?我不知道为什么。

#8


3  

There is a not so well known corner case with generational garbage collectors. (For a brief description read the answer by benjismith for a deeper insight read the articles at the end).

对于分代垃圾收集器来说,有一个不太为人所知的情况。(请阅读benjismith的答案,以获得更深入的见解,请阅读文章的最后部分)。

The idea in generational GCs is that most of the time only young generations need to be considered. The root location is scanned for references, and then the young generation objects are scanned. During this more frequent sweeps no object in the old generation are checked.

代际跨国公司的想法是,大多数时候只需要考虑年轻一代。扫描根位置以查找引用,然后扫描年轻的生成对象。在更频繁的扫描过程中,不检查旧代中的任何对象。

Now, the problem comes from the fact that an object is not allowed to have references to younger objects. When a long lived (old generation) object gets a reference to a new object, that reference must be explicitly tracked by the garbage collector (see article from IBM on the hotspot JVM collector), actually affecting the GC performance.

现在,问题来自于一个对象不允许有对年轻对象的引用。当一个长期存在的(旧一代)对象获得对新对象的引用时,该引用必须由垃圾收集器显式跟踪(请参阅IBM关于hotspot JVM收集器的文章),这实际上会影响GC性能。

The reason why an old object cannot refer to a younger one is that, as the old object is not checked in minor collections, if the only reference to the object is kept in the old object, it will not get marked, and would be wrongly deallocated during the sweep stage.

为什么老对象引用一个不年轻的一个是,由于旧的对象不是检入较小的集合,如果唯一的参考对象保存在旧的对象,它不会被标记,将错误地收回在扫描阶段。

Of course, as pointed by many, the final keyword does not reallly affect the garbage collector, but it does guarantee that the reference will never be changed into a younger object if this object survives the minor collections and makes it to the older heap.

当然,正如许多人指出的那样,final关键字并不会真正影响垃圾收集器,但它确实保证,如果这个对象在小的收集中存活下来,并使它成为旧的堆,那么这个引用将永远不会被更改为更年轻的对象。

Articles:

文章:

IBM on garbage collection: history, in the hotspot JVM and performance. These may no longer be fully valid, as it dates back in 2003/04, but they give some easy to read insight into GCs.

IBM on garbage collection: history, in the hotspot JVM和performance。这些可能不再是完全有效的,因为它可以追溯到2003/04年,但是它们提供了一些对GCs的理解。

Sun on Tuning garbage collection

对垃圾收集进行调优

#9


3  

final on local variables and parameters makes no difference to the class files produced, so cannot affect runtime performance. If a class has no subclasses, HotSpot treats that class as if it is final anyway (it can undo later if a class that breaks that assumption is loaded). I believe final on methods is much the same as classes. final on static field may allow the variable to be interpreted as a "compile-time constant" and optimisation to be done by javac on that basis. final on fields allows the JVM some freedom to ignore happens-before relations.

对于本地变量和参数的final不会影响生成的类文件,因此不会影响运行时性能。如果一个类没有子类,HotSpot就会把这个类当作最终类(如果一个类破坏了这个假设,那么它可以在以后撤销)。我相信最终的方法和课程是一样的。静态字段的final可以将变量解释为“编译时常量”,并在此基础上由javac进行优化。字段的final允许JVM在忽略事件之前有一定的*。

#10


2  

There seems to be a lot of answers that are wandering conjectures. The truth is, there is no final modifier for local variables at the bytecode level. The virtual machine will never know that your local variables were defined as final or not.

似乎有很多答案都是在猜测。事实是,在字节码级别上没有最终的局部变量修改器。虚拟机永远不会知道您的本地变量是否被定义为final。

The answer to your question is an emphatic no.

你的问题的答案显然是否定的。

#11


1  

All method and variable can be overridden bydefault in subclasses.If we want to save the subclasses from overridig the members of superclass,we can declare them as final using the keyword final. For e.g- final int a=10; final void display(){......} Making a method final ensures that the functionality defined in the superclass will never be changed anyway. Similarly the value of a final variable can never be changed. Final variables behaves like class variables.

所有方法和变量都可以在子类中默认重写。如果我们想将子类从overridig超类的成员中保存下来,我们可以使用关键字final将它们声明为final。为e。g -最后一个int = 10;最后的空白显示(){……}制定方法final将确保在超类中定义的功能永远不会被更改。同样,最终变量的值也不能改变。最终变量的行为类似于类变量。

#12


0  

The only thing that I can think of is that the compiler might optimize away the final variables and inline them as constants into the code, thus you end up with no memory allocated.

我能想到的唯一一件事是编译器可能会优化最后的变量,并将它们作为常量内联到代码中,这样就不会分配内存。

#13


0  

absolutely, as long as make object's life shorter which yield great benefit of memory management, recently we examined export functionality having instance variables on one test and another test having method level local variable. during load testing, JVM throws outofmemoryerror on first test and JVM got halted. but in second test, successfully able to get the report due to better memory management.

当然,只要使对象的生命周期更短,从而带来内存管理的巨大好处,最近我们研究了在一个测试中具有实例变量的导出功能,以及在另一个测试中具有方法级局部变量的导出功能。在负载测试期间,JVM在第一次测试中抛出outofmemoryerror, JVM被暂停。但是在第二次测试中,由于更好的内存管理,成功地获得了报告。

#14


0  

The only time I prefer declaring local variables as final is when:

我唯一喜欢声明局部变量为final的时间是:

  • I have to make them final so that they can be shared with some anonymous class (for example: creating daemon thread and let it access some value from enclosing method)

    我必须将它们设置为final,以便它们可以与某个匿名类共享(例如:创建守护进程线程,并让它通过封闭方法访问某些值)

  • I want to make them final (for example: some value that shouldn't/doesn't get overridden by mistake)

    我想让它们成为final(例如:一些不应该被错误覆盖的值)

Does they help in fast garbage collection?
AFAIK a object becomes a candidate of GC collection if it has zero strong references to it and in that case as well there is no guarantee that they will be immediately garbage collected . In general, a strong reference is said to die when it goes out of scope or user explicitly reassign it to null reference, thus, declaring them final means that reference will continue to exists till the method exists (unless its scope is explicitly narrowed down to a specific inner block {}) because you can't reassign final variables. So I think w.r.t Garbage Collection 'final' may introduce a unwanted possible delay.

它们有助于快速垃圾收集吗?如果一个对象没有对它的强引用,那么它将成为GC收集的候选对象,而且在这种情况下,也不能保证它们会立即被垃圾收集。一般来说,一个强引用据说死时超出范围或用户显式地重新分配空引用,因此,宣布他们将继续存在,直到最终意味着参考方法存在(除非明确其范围缩小到一个特定的内部块{ })因为你不能重新分配最终变量。所以我认为w.r。垃圾收集的“最终”可能会带来不希望的延迟。

#1


80  

Here's a slightly different example, one with final reference-type fields rather than final value-type local variables:

这里有一个稍微不同的例子,一个具有最终引用类型字段而不是最终值类型局部变量的例子:

public class MyClass {

   public final MyOtherObject obj;

}

Every time you create an instance of MyClass, you'll be creating an outgoing reference to a MyOtherObject instance, and the GC will have to follow that link to look for live objects.

每次创建MyOtherObject类的实例时,都将创建一个对MyOtherObject实例的传出引用,GC必须遵循该链接来查找活动对象。

The JVM uses a mark-sweep GC algorithm, which has to examine all the live refereces in the GC "root" locations (like all the objects in the current call stack). Each live object is "marked" as being alive, and any object referred to by a live object is also marked as being alive.

JVM使用标记-清除GC算法,它必须检查GC“根”位置中的所有活动引用(就像当前调用堆栈中的所有对象一样)。每个活动对象都被“标记”为“活着”,任何被活动对象引用的对象也被标记为“活着”。

After the completion of the mark phase, the GC sweeps through the heap, freeing memory for all unmarked objects (and compacting the memory for the remaining live objects).

标记阶段完成后,GC遍历堆,释放所有未标记对象的内存(并压缩其余活动对象的内存)。

Also, it's important to recognize that the Java heap memory is partitioned into a "young generation" and an "old generation". All objects are initially allocated in the young generation (sometimes referred to as "the nursery"). Since most objects are short-lived, the GC is more aggressive about freeing recent garbage from the young generation. If an object survives a collection cycle of the young generation, it gets moved into the old generation (sometimes referred to as the "tenured generation"), which is processed less frequently.

此外,重要的是要认识到Java堆内存被划分为“年轻一代”和“老一代”。所有对象最初都分配给年轻一代(有时称为“托儿所”)。由于大多数对象都是短期的,所以GC在从年轻一代中释放最近的垃圾时更加积极。如果一个对象在年轻一代的集合周期中存活下来,那么它将被转移到老一代(有时被称为“长期一代”)中,这一过程处理得更少。

So, off the top of my head, I'm going to say "no, the 'final' modifer doesn't help the GC reduce its workload".

因此,在我的脑海中,我会说“不,‘最终’修改器不能帮助GC减少它的工作负载”。

In my opinion, the best strategy for optimizing your memory-management in Java is to eliminate spurious references as quickly as possible. You could do that by assigning "null" to an object reference as soon as you're done using it.

在我看来,优化Java内存管理的最佳策略是尽可能快地消除虚假引用。您可以通过在使用对象引用时将“null”分配给对象引用来实现这一点。

Or, better yet, minimize the size of each declaration scope. For example, if you declare an object at the beginning of a 1000-line method, and if the object stays alive until the close of that method's scope (the last closing curly brace), then the object might stay alive for much longer that actually necessary.

或者,更好的是,最小化每个声明范围的大小。例如,如果您在一个1000行方法的开头声明一个对象,并且如果该对象在该方法的作用域(最后一个闭花括号)结束之前保持活动状态,那么该对象可能会在实际需要的时间内保持活动状态。

If you use small methods, with only a dozen or so lines of code, then the objects declared within that method will fall out of scope more quickly, and the GC will be able to do most of its work within the much-more-efficient young generation. You don't want objects being moved into the older generation unless absolutely necessary.

如果您使用的方法很小,只有十几行代码,那么该方法中声明的对象将更快地退出范围,GC将能够在效率更高的年轻一代中完成大部分工作。除非绝对必要,否则不希望对象被转移到老一代。

#2


36  

Declaring a local variable final will not affect garbage collection, it only means you can not modify the variable. Your example above should not compile as you are modifying the variable totalWeight which has been marked final. On the other hand, declaring a primitive (double instead of Double) final will allows that variable to be inlined into the calling code, so that could cause some memory and performance improvement. This is used when you have a number of public static final Strings in a class.

声明局部变量final不会影响垃圾收集,它只意味着不能修改该变量。上面的示例不应该编译,因为您正在修改已标记为final的变量totalWeight。另一方面,声明一个原语(double而不是double) final将允许将该变量内联到调用代码中,因此可能会导致一些内存和性能改进。当类中有许多公共静态最终字符串时,可以使用此方法。

In general, the compiler and runtime will optimize where it can. It is best to write the code appropriately and not try to be too tricky. Use final when you do not want the variable to be modified. Assume that any easy optimizations will be performed by the compiler, and if you are worried about performance or memory use, use a profiler to determine the real problem.

一般来说,编译器和运行时将在它能优化的地方进行优化。最好是适当地编写代码,而不要太复杂。当不希望修改变量时使用final。假设编译器将执行任何简单的优化,如果您担心性能或内存使用,请使用分析器来确定真正的问题。

#3


24  

No, it is emphatically not true.

不,这绝对不是真的。

Remember that final does not mean constant, it just means you can't change the reference.

记住,final不是指常数,它只是表示你不能改变引用。

final MyObject o = new MyObject();
o.setValue("foo"); // Works just fine
o = new MyObject(); // Doesn't work.

There may be some small optimisation based around the knowledge that the JVM will never have to modify the reference (such as not having check to see if it has changed) but it would be so minor as to not worry about.

基于JVM永远不需要修改引用的知识(比如不检查是否修改引用),可能会有一些小的优化,但是这些优化非常小,以至于不必担心。

Final should be thought of as useful meta-data to the developer and not as a compiler optimisation.

Final应该被视为对开发人员有用的元数据,而不是编译器优化。

#4


15  

Some points to clear up:

有几点需要澄清:

  • Nulling out reference should not help GC. If it did, it would indicate that your variables are over scoped. One exception is the case of object nepotism.

    取消引用不应该帮助GC。如果它这样做了,它将表明您的变量的作用域超出了范围。对象裙带关系是一个例外。

  • There is no on-stack allocation as of yet in Java.

    在Java中还没有堆栈分配。

  • Declaring a variable final means you can't (under normal conditions) assign a new value to that variable. Since final says nothing about scope, it doesn't say anything about it's effect on GC.

    声明变量final意味着您不能(在正常情况下)为该变量赋新值。因为final没有说明范围,它没有说明它对GC的影响。

#5


10  

Well, I don't know about the use of the "final" modifier in this case, or its effect on the GC.

我不知道在这种情况下如何使用“final”修饰符,或者它对GC的影响。

But I can tell you this: your use of Boxed values rather than primitives (e.g., Double instead of double) will allocate those objects on the heap rather than the stack, and will produce unnecessary garbage that the GC will have to clean up.

但是我可以告诉您:您使用装箱值而不是原语(例如,Double而不是Double)将在堆上而不是堆栈上分配这些对象,并将产生GC必须清理的不必要的垃圾。

I only use boxed primitives when required by an existing API, or when I need nullable primatives.

我只在现有API需要的时候使用封装的原语,或者在需要可空的原语的时候使用。

#6


5  

Final variables cannot be changed after initial assignment (enforced by the compiler).

在初始分配(由编译器执行)之后,不能更改最终变量。

This does not change the behaviour of the garbage collection as such. Only thing is that these variables cannot be nulled when not being used any more (which may help the garbage collection in memory tight situations).

这不会改变垃圾收集的行为。惟一的问题是,这些变量在没有被使用时不能被取消(这可能有助于在内存紧张的情况下收集垃圾)。

You should know that final allows the compiler to make assumptions about what to optimize. Inlining code and not including code known not to be reachable.

您应该知道,final允许编译器假设要优化什么。内联代码,不包括已知不可访问的代码。

final boolean debug = false;

......

if (debug) {
  System.out.println("DEBUG INFO!");
}

The println will not be included in the byte code.

将不会在字节代码中包含println。

#7


3  

GC acts on unreachable refs. This has nothing to do with "final", which is merely an assertion of one-time assignment. Is it possible that some VM's GC can make use of "final"? I don't see how or why.

GC作用于无法到达的裁判。这与“最终”没有关系,“最终”只是一次性分配的断言。是否有些VM的GC可以使用“final”?我不知道为什么。

#8


3  

There is a not so well known corner case with generational garbage collectors. (For a brief description read the answer by benjismith for a deeper insight read the articles at the end).

对于分代垃圾收集器来说,有一个不太为人所知的情况。(请阅读benjismith的答案,以获得更深入的见解,请阅读文章的最后部分)。

The idea in generational GCs is that most of the time only young generations need to be considered. The root location is scanned for references, and then the young generation objects are scanned. During this more frequent sweeps no object in the old generation are checked.

代际跨国公司的想法是,大多数时候只需要考虑年轻一代。扫描根位置以查找引用,然后扫描年轻的生成对象。在更频繁的扫描过程中,不检查旧代中的任何对象。

Now, the problem comes from the fact that an object is not allowed to have references to younger objects. When a long lived (old generation) object gets a reference to a new object, that reference must be explicitly tracked by the garbage collector (see article from IBM on the hotspot JVM collector), actually affecting the GC performance.

现在,问题来自于一个对象不允许有对年轻对象的引用。当一个长期存在的(旧一代)对象获得对新对象的引用时,该引用必须由垃圾收集器显式跟踪(请参阅IBM关于hotspot JVM收集器的文章),这实际上会影响GC性能。

The reason why an old object cannot refer to a younger one is that, as the old object is not checked in minor collections, if the only reference to the object is kept in the old object, it will not get marked, and would be wrongly deallocated during the sweep stage.

为什么老对象引用一个不年轻的一个是,由于旧的对象不是检入较小的集合,如果唯一的参考对象保存在旧的对象,它不会被标记,将错误地收回在扫描阶段。

Of course, as pointed by many, the final keyword does not reallly affect the garbage collector, but it does guarantee that the reference will never be changed into a younger object if this object survives the minor collections and makes it to the older heap.

当然,正如许多人指出的那样,final关键字并不会真正影响垃圾收集器,但它确实保证,如果这个对象在小的收集中存活下来,并使它成为旧的堆,那么这个引用将永远不会被更改为更年轻的对象。

Articles:

文章:

IBM on garbage collection: history, in the hotspot JVM and performance. These may no longer be fully valid, as it dates back in 2003/04, but they give some easy to read insight into GCs.

IBM on garbage collection: history, in the hotspot JVM和performance。这些可能不再是完全有效的,因为它可以追溯到2003/04年,但是它们提供了一些对GCs的理解。

Sun on Tuning garbage collection

对垃圾收集进行调优

#9


3  

final on local variables and parameters makes no difference to the class files produced, so cannot affect runtime performance. If a class has no subclasses, HotSpot treats that class as if it is final anyway (it can undo later if a class that breaks that assumption is loaded). I believe final on methods is much the same as classes. final on static field may allow the variable to be interpreted as a "compile-time constant" and optimisation to be done by javac on that basis. final on fields allows the JVM some freedom to ignore happens-before relations.

对于本地变量和参数的final不会影响生成的类文件,因此不会影响运行时性能。如果一个类没有子类,HotSpot就会把这个类当作最终类(如果一个类破坏了这个假设,那么它可以在以后撤销)。我相信最终的方法和课程是一样的。静态字段的final可以将变量解释为“编译时常量”,并在此基础上由javac进行优化。字段的final允许JVM在忽略事件之前有一定的*。

#10


2  

There seems to be a lot of answers that are wandering conjectures. The truth is, there is no final modifier for local variables at the bytecode level. The virtual machine will never know that your local variables were defined as final or not.

似乎有很多答案都是在猜测。事实是,在字节码级别上没有最终的局部变量修改器。虚拟机永远不会知道您的本地变量是否被定义为final。

The answer to your question is an emphatic no.

你的问题的答案显然是否定的。

#11


1  

All method and variable can be overridden bydefault in subclasses.If we want to save the subclasses from overridig the members of superclass,we can declare them as final using the keyword final. For e.g- final int a=10; final void display(){......} Making a method final ensures that the functionality defined in the superclass will never be changed anyway. Similarly the value of a final variable can never be changed. Final variables behaves like class variables.

所有方法和变量都可以在子类中默认重写。如果我们想将子类从overridig超类的成员中保存下来,我们可以使用关键字final将它们声明为final。为e。g -最后一个int = 10;最后的空白显示(){……}制定方法final将确保在超类中定义的功能永远不会被更改。同样,最终变量的值也不能改变。最终变量的行为类似于类变量。

#12


0  

The only thing that I can think of is that the compiler might optimize away the final variables and inline them as constants into the code, thus you end up with no memory allocated.

我能想到的唯一一件事是编译器可能会优化最后的变量,并将它们作为常量内联到代码中,这样就不会分配内存。

#13


0  

absolutely, as long as make object's life shorter which yield great benefit of memory management, recently we examined export functionality having instance variables on one test and another test having method level local variable. during load testing, JVM throws outofmemoryerror on first test and JVM got halted. but in second test, successfully able to get the report due to better memory management.

当然,只要使对象的生命周期更短,从而带来内存管理的巨大好处,最近我们研究了在一个测试中具有实例变量的导出功能,以及在另一个测试中具有方法级局部变量的导出功能。在负载测试期间,JVM在第一次测试中抛出outofmemoryerror, JVM被暂停。但是在第二次测试中,由于更好的内存管理,成功地获得了报告。

#14


0  

The only time I prefer declaring local variables as final is when:

我唯一喜欢声明局部变量为final的时间是:

  • I have to make them final so that they can be shared with some anonymous class (for example: creating daemon thread and let it access some value from enclosing method)

    我必须将它们设置为final,以便它们可以与某个匿名类共享(例如:创建守护进程线程,并让它通过封闭方法访问某些值)

  • I want to make them final (for example: some value that shouldn't/doesn't get overridden by mistake)

    我想让它们成为final(例如:一些不应该被错误覆盖的值)

Does they help in fast garbage collection?
AFAIK a object becomes a candidate of GC collection if it has zero strong references to it and in that case as well there is no guarantee that they will be immediately garbage collected . In general, a strong reference is said to die when it goes out of scope or user explicitly reassign it to null reference, thus, declaring them final means that reference will continue to exists till the method exists (unless its scope is explicitly narrowed down to a specific inner block {}) because you can't reassign final variables. So I think w.r.t Garbage Collection 'final' may introduce a unwanted possible delay.

它们有助于快速垃圾收集吗?如果一个对象没有对它的强引用,那么它将成为GC收集的候选对象,而且在这种情况下,也不能保证它们会立即被垃圾收集。一般来说,一个强引用据说死时超出范围或用户显式地重新分配空引用,因此,宣布他们将继续存在,直到最终意味着参考方法存在(除非明确其范围缩小到一个特定的内部块{ })因为你不能重新分配最终变量。所以我认为w.r。垃圾收集的“最终”可能会带来不希望的延迟。