Does using final for variables in Java improve garbage collection?

后端 未结 15 2028
南笙
南笙 2020-11-29 18:01

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

For example, if you write a

相关标签:
15条回答
  • 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.

    0 讨论(0)
  • 2020-11-29 18:22

    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).

    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.

    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.

    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.

    Sun on Tuning garbage collection

    0 讨论(0)
  • 2020-11-29 18:22

    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.

    0 讨论(0)
  • 2020-11-29 18:24

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

    • 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)

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

    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 (i.e. can't reassign to null). So I think w.r.t Garbage Collection 'final' may introduce a unwanted possible delay so one must be little careful in defining there scope as that controls when they will become candidate for GC.

    0 讨论(0)
  • 2020-11-29 18:25

    Strictly speaking about instance fields, final might improve performance slightly if a particular GC wants to exploit that. When a concurrent GC happens (that means that your application is still running, while GC is in progress), see this for a broader explanation, GCs have to employ certain barriers when writes and/or reads are done. The link I gave you pretty much explains that, but to make it really short: when a GC does some concurrent work, all read and writes to the heap (while that GC is in progress), are "intercepted" and applied later in time; so that the concurrent GC phase can finish it's work.

    For final instance fields, since they can not be modified (unless reflection), these barriers can be omitted. And this is not just pure theory.

    Shenandoah GC has them in practice (though not for long), and you can do, for example:

    -XX:+UnlockExperimentalVMOptions  
    -XX:+UseShenandoahGC  
    -XX:+ShenandoahOptimizeInstanceFinals
    

    And there will be optimizations in the GC algorithm that will make it slightly faster. This is because there will be no barriers intercepting final, since no one should modify them, ever. Not even via reflection or JNI.

    0 讨论(0)
  • 2020-11-29 18:27

    No, it is emphatically not true.

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

    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.

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

    0 讨论(0)
提交回复
热议问题