Does using final for variables in Java improve garbage collection?

后端 未结 15 2018
南笙
南笙 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条回答
  • 2020-11-29 18:27

    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.

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

    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.

    • There is no on-stack allocation as of yet in 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.

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

    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 boolean debug = false;
    
    ......
    
    if (debug) {
      System.out.println("DEBUG INFO!");
    }
    

    The println will not be included in the byte code.

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

    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.

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

    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.

    The answer to your question is an emphatic no.

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

    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.

    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.

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

    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.

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

    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.

    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.

    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.

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