Does it help GC to null local variables in Java

2019-01-10 12:33发布

I was 'forced' to add myLocalVar = null; statement into finally clause just before leaving method. Reason is to help GC. I was told I will get SMS's during night when server crashes next time, so I better did it :-).

I think this is pointless, as myLocalVar is scoped to method, and will be 'lost' as soon as method exits. Extra nulling just pollutes the code, but is harmless otherwise.

My question is, where does this myth about helping GC come from? (I was referred to "Java memory books") Do you know any article from 'authorities' which explain it in more depth? Is there possibility this is not a myth, but really helps somehow? If so, how? May nulling local variables cause any harm?

To clarify, method look like this:

void method() {
  MyClass myLocalVar = null;
  try {
    myLocalVar = get reference to object;
    ... do more here ...
  } finally {
    if (myLocalVar != null) {
      myLocalVar.close(); // it is resource which we should close
    }

    myLocalVar = null; // THIS IS THE LINE I AM TALKING ABOUT
  }
}

15条回答
我欲成王,谁敢阻挡
2楼-- · 2019-01-10 13:04

The Java GC is supposed to be "sound" but is not necessarily immediately "complete". In other words, it is designed so that it would never eliminate objects that are still accessible by at least one path (and thus cause a dangling reference). It is not necessarily immediately complete since it might take time until it removes everything that can be removed.

I think that most GC myths come from a misunderstanding of that concept. Many people keep too many instance variables alive, and that causes problems, but that is of course not the issue here.

Other people put the local variables in an instance variable (e.g., by passing it to function), and then think that nullifying the local variable somehow eliminates the variable, which is of course untrue.

Finally, there are people who overrely on the GC and think it would do functional shutdown for them (E.g., close connections when variable is removed) which is of course not the case. I think the source of this line is the "I'm really really done with it but I'm not sure how to ensure that".

So yeah, you're correct that it's unneccessary.

查看更多
冷血范
3楼-- · 2019-01-10 13:04

In some circumstances, it can be useful to null variables (usually instance or class variables). But nulling a local variable immediately before the end of the method does absolutely nothing.

When you set a variable to null, you are merely removing that reference to the actual object. But when a local variable goes out of scope, the reference is removed anyway; therefore, setting it to null as the last line of the method is simply redundant.

查看更多
你好瞎i
4楼-- · 2019-01-10 13:05

Not only is nulling a local variable like that meaningless in terms of GC, it may cause unnecessary loading of the variable into a register in order to null it out, which makes the situation worse. Imagine if there is 1000 lines of code between the last read or write to myLocalVar, and then you reference it just to null out the reference. The value is long gone from the register, but you have to load it back in to memory to work with it.

查看更多
冷血范
5楼-- · 2019-01-10 13:11

To the best of my knowledge, nulling a variable immediately before it leaves the scope makes no difference to the garbage collector.

Of course there are cases where it indeed does help. E.g. when var is not a local variable but a member or static member. Then destroying the reference might make the object unreachable and thus eligible for collection.

Another case where it might help even with local variables if a function allocates much temporary memory to initialise some data for further processing and can throw away all references to the temporary memory before beginning the processing:

SomeResult SomeFunction(SomeClass param) {
    TempData big = new TempData(param);
    IntermediateResult intermediate = big.GetIntermediateResult();
    big = null; // allow GC to reclaim the memory before returning from the function
    intermediate.FurtherProcessing();
    return intermediate.EvenMoreProcessing();
}
查看更多
混吃等死
6楼-- · 2019-01-10 13:11

If your class hangs around for a long time, then nulling out objects it references will allow them to be collected.

This is almost never an issue, most times nulling objects is not useful.

When you think of object allocation and freeing, pay attention to the things that the "System" has handles to: Active threads, windows that haven't been dispose()d, and one or two more things but I can't remember right now.

Every object in your system "Hangs" off these mount points in a giant upside-down tree. If you cut any branch free from these "Roots" the entire branch falls to the ground and is collected by the Lawn Mower of Garbage Collecting.

Most classes need all their member variables for their entire lifecycle--and when their life is finished, their entire branch is trimmed including all their members; hence--no need to null.

(these trims, by the way, are quite efficient, even more than C++'s free since they don't require touching each object as it's freed)

查看更多
淡お忘
7楼-- · 2019-01-10 13:13

Another possible factor in this myth is that it can make a difference to null out a local variable if you are done with it before the end of the method. This would allow the GC to collect that object before the method is complete, which could be useful.

Someone might have been given that advice at some point and misunderstood it as a need to always null out the local variables.

查看更多
登录 后发表回答