views:

1300

answers:

6

I was browsing some old books and found a copy of "Practical Java" by Peter Hagger. In the performance section, there is a recommendation to set object references to null when no longer needed.

In Java, does setting object references to null improve performance or garbage collection efficiency? If so, in what cases is this an issue? Container classes? Object composition? Anonymous inner classes?

I see this in code pretty often. Is this now obsolete programming advice or is it still useful?

+12  A: 

No, it's not obsolete advice. Dangling references are still a problem, especially if you're, say, implementing an expandable array container (ArrayList or the like) using a pre-allocated array. Elements beyond the "logical" size of the list should be nulled out, or else they won't be freed.

See Effective Java 2nd ed, Item 6: Eliminate Obsolete Object References.

Chris Jester-Young
Is this a language issue or a VM implementation issue?
Pablo Santa Cruz
It's a "semantic" issue. Basically, because you've preallocated an array, the VM sees that. It knows nothing about the "logical" size of your container. Say you have an ArrayList of size 10, backed by a 16-element array. The VM can't know that items 10..15 aren't actually used; if those slots have contents, they will not be freed.
Chris Jester-Young
what about outside of container classes? In object composition where the inner object isn't de-allocated by the outer object is.
sal
@sal The general rule of thumb is that if you can't reference it, it gets garbage collected. So if the outer object contains a reference to another object, assuming that the inner object does not have any other references, setting the outer object's one and only reference to null will cause the entire object to be garbage collected, including its orphaned references.
ubermensch
+2  A: 

In memory restrictive environments (e.g. cellphones) this can be useful. By setting null, the objetc don't need to wait the variable to get out of scope to be gc'd.

For the everyday programming, however, this shouldn't be the rule, except in special cases like the one Chris Jester-Young cited.

Renato Besen
A: 

Settting an object to null also shows that the programmer is 'done' with it. I usually .close() BufferedReaders for the same reason. The added advantage with this is that if you then try and call an object which you have de-referenced to null you'll get a NullPointerException, so you'll know about it quite quickly.

Catchwa
that's a bit of a different issue - you probably want to explicitly close any underlying streams (and as soon as you can)
matt b
+12  A: 

It depends a bit on when you were thinking of nulling the reference.

If you have an object chain A->B->C, then once A is not reachable, A, B and C will all be eligible for garbage collection (assuming nothing else is referring to either B or C). There's no need, and never has been any need, to explicitly set references A->B or B->C to null, for example.

Apart from that, most of the time the issue doesn't really arise, because in reality you're dealing with objects in collections. You should generally always be thinking of removing objects from lists, maps etc by calling the appropiate remove() method.

The case where there used to be some advice to set references to null was specifically in a long scope where a memory-intensive object ceased to be used partway through the scope. For example:

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;             <-- explicitly set to null
  doSomethingElse();
}

The rationale here was that because obj is still in scope, then without the explicit nulling of the reference, it does not become garbage collectable until after the doSomethingElse() method completes. And this is the advice that probably no longer holds on modern JVMs: it turns out that the JIT compiler can work out at what point a given local object reference is no longer used.

Neil Coffey
+2  A: 

Instance fields, array elements

If there is a reference to an object, it cannot be garbage collected. Especially if that object (and the whole graph behind it) is big, there is only one reference that is stopping garbage collection, and that reference is not really needed anymore, that is an unfortunate situation.

Pathological cases are the object that retains an unnessary instance to the whole XML DOM tree that was used to configure it, the MBean that was not unregistered, or the single reference to an object from an undeployed web application that prevents a whole classloader from being unloaded.

So unless you are sure that the object that holds the reference itself will be garbage collected anyway (or even then), you should null out everything that you no longer need.

Scoped variables:

If you are considering setting a local variable to null before the end of its scope , so that it can be reclaimed by the garbage collector and to mark it as "unusable from now on", you should consider putting it in a more limited scope instead.

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;          //   <-- explicitly set to null
  doSomethingElse();
}

becomes

{
  {  
     BigObject obj = ...
     doSomethingWith(obj);
  }    //         <-- obj goes out of scope
  doSomethingElse();
}

Long, flat scopes are generally bad for legibility of the code, too. Introducing private methods to break things up just for that purpose is not unheard of, too.

Thilo
+1  A: 

An object cannot be claimed by the garbage collector while there is still any references to it, i.e. the value returned by "new Whatever()" stored anywhere. It is therefore good practice to ensure that no dangling references linger (deep in data structures etc), in order to avoid memory leaks. This is usually done in one of several ways:

  • The scope of the variable ends - this means variables inside a method "vanish" when the method is done and any references stored in them automatically go away.
  • The class containing a variable reference is garbage collected. For instance a list of objects, contains a lot of object references, which you do not need to clean manually. You can just let the list object be garbage collected and don't care about the contents.
  • Explicitly set a variable containing a reference to null.

Setting to null is the only one where the programmer explicitly does something. This is usually to tell SOMEBODY that the object is not used anymore. The SOMEBODY could be

  • Garbage collector. A very large object may be not used anymore. By nulling this explicitly the garbage collector may reuse that area without having to wait for the variable to fall out of scope. As a collolary such areas of code may be put in an additional set of brackets to limit scope.
  • Maintainer! Explicitly nulling a variable tells a human reader that the object previously kept in there is not used anymore and does not have to be mentally dealt with. This can usually be achieved better with refactoring into an additional method, but may be necessary for global variables as they don't fall out of scope when leaving a method.

So, basically there is a reason for explicitly nulling variables. The original writer of the code should leave a comment saying WHY it is done if it is not explicitly written in the coding convention used.

Thorbjørn Ravn Andersen