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 12:57

You are correct. Nulling out a variable that will immediately fall out of scope anyway is unnecessary and makes no difference whatsoever to GC. All it does is clutter the code. In Effective Java 2nd Edition, the author recommends against unnecessary nulling out of local variables. See Effective Java, 2nd Edition, Item 6: Eliminate obsolete object references, for a full writeup.

You can also see this in the article Creating and Destroying Java Objects, at InformIT. Read the entire article to find the place where Joshua Bloch agrees with you.

When a local variable falls out of scope, it is exactly the same as if you null the reference to it.

EDIT: Add link to Effective Java 2nd Edition at Sun website

查看更多
对你真心纯属浪费
3楼-- · 2019-01-10 13:00

If you don't need large objects in your local scope anymore, you can give the JVM a hint and set the reference NULL.

public void foobar()
{
    List<SomeObject> dataList = new ArrayList<SomeObject>();

    // heavy computation here where objects are added to dataList 
    // and the list grows, maybe you will sort the list and
    // you just need the first element... 

    SomeObject smallest = dataList.get(0);

    // more heavy computation will follow, where dataList is never used again
    // so give the JVM a hint to drop it on its on discretion
    dataList = null;

    // ok, do your stuff other heavy stuff here... maybe you even need the 
    // memory that was occupied by dataList before... 

    // end of game and the JVM will take care of everything, no hints needed
}

But it does not make sense before the return, because this is done by the JVM automatically. So I agree with all postings before.

查看更多
【Aperson】
4楼-- · 2019-01-10 13:02

Not in this case. myLocalVar falls out of scope as soon as the function returns, so setting the reference to null does absolutely nothing.

查看更多
成全新的幸福
5楼-- · 2019-01-10 13:02

As you correctly point out, nulling out in this case is totally pointless.

Back on JDK1.3 I did actually have a case with an extremely large object graph that also contained lots of circular references within the graph. Clearing out a few of the references did actually improve GC times quite noticeably.

I am not sure if this would apply with a modern VM. Garbage collectors have become increasingly smarter.

查看更多
放荡不羁爱自由
6楼-- · 2019-01-10 13:02

I don't know the technical details, but as far as I can remember, the variable is nothing more than reference from the current stack frame, and until this reference is removed, the object cannot be garbage collected. Now, but explicitly setting it to null, you've made sure that the reference is gone. If you don't you're basically letting the VM decide when this reference is cleared, which might or might not be upon exiting the scope (unlike C++, if the object is located on the stack and MUST be destroyed). It might be when the stack frame is overwritten with the next. I'm not sure if there's actually a VM which does this.

Short answer though, it's unnecessary, the mark and sweep will get it eventually. It's at most a question of time.

查看更多
小情绪 Triste *
7楼-- · 2019-01-10 13:03

There are only two cases where I have found setting a variable to null has been useful:

  • In unit tests which create a large object in a field. The unit tester may retain the test object and the objects you created for the life of all the tests. This can cause the tester to run out of memory. In this case it is often better to use local variables instead of fields, but if a field required it can be cleared in the tearDown.
  • Circular references can be cleaned up by the GC but not with a simple incremental collection. This can mean that objects with circular references take more work to clear and can live much long than they would otherwise. Generally this doesn't matter but if you are trying to reduce your full GC time, it can help to break circular references.
查看更多
登录 后发表回答