Java: how to store references to all instances of a class? - java

I'm more used to C++. To get a list of all instances of a class (this is a library class that can be extended by the user), I usually have a static container with all references to such objects:
#include <list>
class CPPClass;
class CPPClass {
public:
CPPClass() {
objList.push_back(this);
}
~CPPClass() {
objList.remove(this);
}
private:
static std::list<CPPClass *> objList;
};
std::list<CPPClass *> CPPClass::objList;
How should I do the same in Java? I have a few concerns:
someone mentioned to me that there can be multiple classloaders, and that might cause problems
there is no destructor in java, so how would the references be removed from the list?
if the references are not removed, when do these objects get garbage-collected?

Easy things first: multiple classloaders won't cause you a problem unless you use a non-standard delegation pattern (with a custom classloader). If you do have such a non-standard classloader, you can get a situation wheredifferent parts of the app are using different versions of the CPPClass class (each version from a different ClassLoader). This has various issues (you can get a ClassCastException casting from CPPClass to CPPClass!), but it shouldn't affect your static collection; each CPPClass will just have its own, separate collection.
Next thing: don't add the objects to the collection from the constructor. Leaking the this reference from a constructor can lead to memory model problems. Instead, you should create a static factory method that creates the object and then separately adds it to the static collection. That collection should also be thread-safe, of course.
Finally, the core question. If each object is not equal to any other object (that is, if you haven't overridden Object.equals), you could use a WeakHashMap, with the objects as keys. If the class does override equals, you can create a collection of WeakReferences, which you can prune at convenient times (on insert, on retrieving the list, etc.). A WeakReference will not prevent the object it refers to from being GCed -- it'll just return null from get after that GC has happened.
But if I may editorialize a bit, "solutions" like this often hint at an ill-defined object lifecycle, which has other maintainability issues. It could be better if your objects implement Closeable or have a similar way for the code that uses them to declare that it's finished with them.

Rather than storing a reference to an object, store a WeakReference to the object - this way the garbage collector will free the object if the WeakReference is the only reference that remains.

You can indeed make the list static, just make sure you also initialise it properly.
List<CPPClass> objlist;
static {
objlist = new List<CPPClass>();
}
Or something similar should do that.
If you do not remove the reference, it will never get garbage collected because the garbage collector will assume the object is still in use.
There is something that seems a bit like a destructor: the method finalize. But because this method is only called by the garbage collector and you can not use it yourself, it will be of no use to you.

Related

Change a Non Static Variable to Static Variable

I am reading about the GC and read that when an object becomes eligible for garbage collection, the GC has to run the finalize method on it. The finalize method is guaranteed to run only once, thus the GC marks the object as finalized and gives it a rest until the next cycle.
In the finalize method, you can technically “resurrect” an object, for example, by assigning it to a static field. The object would become alive again and not eligible for garbage collection, so the GC would not collect it during the next cycle.
The object, however, would be marked as finalized, so when it would become eligible again, the finalize method would not be called. In essence, you can turn this “resurrection” trick only once for the lifetime of the object.
I find this fascinating. However, if my variable is non-static, how to I change it to the static inside the finalize method?
Remember:
An object becomes eligible for Garbage collection or GC if it is not reachable from any live threads or by any static references. So the hack is to add the object to a static resource inside the finalize method and this will prevent the garbage collection for only one time. The finalize method is protected, so, can be overridden by subclasses, whether they are in the same package or not.
This is a dangerous practice and no need to use inside application code.
Changing a variable definition at runtime isn't easy and in some cases next to impossible. There might be some nasty reflection tricks that might involve inline compiling, classloading etc. but you shouldn't do that. Changing a variable from static to non-static or vice versa would also involve moving the data around in storage and deal with potential collisions - so don't do that.
Anyways variables are just references and to resurrect an object you'd just need to create a new reference from a live thread. That could be done with some collection that's referenced by a static variable and which the this reference is added to.
Example (for illustration purposes only, do not use it unless you really know what you are doing and have a good reason to):
class NastyResurrector {
public static Collection<Object> RESURRECTED_OBJECTS = ...;// use whatever collection implementation you like
}
Then in finalize() you'd call NastyResurrector.RESURRECTED_OBJECTS.add(this) and there you have your reference.
However, I'll quote from the source of your question (question Q11):
Beware that this ugly hack should be used only if you really know what you’re doing
That's the most important takeaway in my opinion.

How do Immutable Objects help decrease overhead due to Garbage Collection?

I am a newb, and I have read about Garbage Collection from the first two answers here.
Now justifying the use of Immutable Objects even if the programmer has to create new objects, as compared to using existing objects (in multi-threaded applications), this tutorial says that the cost of object creation is made up for by the decrease in memory overhead due to garbage collection, and the elimination of code to protect mutable objects from threads interference and memory consistency errors:
The impact of object creation is often overestimated, and can be
offset by some of the efficiencies associated with immutable objects.
These include decreased overhead due to garbage collection, and
the elimination of code needed to protect mutable objects from
corruption.
The question is how? What does Garbage Collection have to do with Mutability or Immutability of objects?
Sometimes you allocate less when objects are immutable.
Simple example
Date getDate(){
return copy(this.date);
}
I have to copy Date every time I share it because it is mutable or the caller would be able to mutate it. If getDate get called a lot,the allocation rate will dramatically increase and this would put pressure on the GC
On the other hand, Java-8 dates are immutable
LocalDate getDate(){
return this.date;
}
Notice that I don't need to copy date (allocate a new object) because of immutability ( I am happy to share the object with you because I know that you can't mutate it).
Now you might think how can I apply this to "useful" or complicated data structures without causing massive allocation (due to defensive copies), you are absolutely right, but there is an art called functional programming and persistent data structures ( ie: you get the illusion that it's a new copy where in fact copies share a lot from the original).
One shouldn't be surprised that most functional languages (all the ones that I am aware of) are garbage collected.
Immutable objects do not need a defensive copy if you are sharing them across contexts (.e.g calling code you don't trust) or for thread safety. This can mean that reads of immutable objects can be lower in terms of garbage.
On the other hand, every time you change an immutable object, you have to create new objects whether this is required or not. In this regard, immutable objects can create far more garbage.
The real question is whether you are making lots of reads, or lots of writes (or a mix) Depending on usage Immutable objects can save objects or create more objects, so it makes sense to use either Immutable or Mutable object based on your specific use case.
Note: most of the time, correctness is far, far more important than performance, and while in general Immutable objects have higher overhead IMHO, it is far easier to prove the correctness of data models using Immutable objects, and it is worth using immutable objects for clarity and ease of reasoning alone.
In this article Brian Goetz explains it nicely. Basically, it is related with the way garbage collector works. It has less work to do if new objects reference the old ones than vice versa.
Excerpt from the linked article with example classes below:
public class MutableHolder {
private Object value;
public Object getValue() { return value; }
public void setValue(Object o) { value = o; }
}
public class ImmutableHolder {
private final Object value;
public ImmutableHolder(Object o) { value = o; }
public Object getValue() { return value; }
}
In most cases, when a holder object is updated to reference a
different object, the new referent is a young object. If we update a
MutableHolder by calling setValue(), we have created a situation
where an older object references a younger one. On the other hand, by
creating a new ImmutableHolder object instead, a younger object is
referencing an older one.
The latter situation, where most objects point to older objects, is
much more gentle on a generational garbage collector. If a
MutableHolder that lives in the old generation is mutated, all the
objects on the card that contain the MutableHolder must be scanned
for old-to-young references at the next minor collection.
The use of mutable references for long-lived container objects
increases the work done to track old-to-young references at collection
time.
Escape analysis
Regarding the concern that lots of objects are created because you instantiate a new object whenever you need to change the existing one, the object allocation mechanism is much improved in latest JVMs.
Take a look at escape analysis (also mentioned in the linked article). Many object will not be allocated on heap (but be inlined/allocated on stack), so GC will have nothing to do with them (actually GC is not aware that those objects exist at all).
Although not related only to immutability, escape analysis mechanism can be utilised more efficiently in an immutable context (an example is the Person object which is not changed during the method invocation in the linked Oracle docs).

Java: practical use of PhantomReference? [duplicate]

The only thing I know about PhantomReference is,
If you use its get() method, it will always return null and not the object. What's the use of it?
By using PhantomReference, you make it sure that the object cannot be resurrected from finalize method.
But what is the use of this concept/class?
Have you ever used this in any of your project or do you have any example where we should use this?
I used PhantomReferences in a simplistic, very specialized kind of memory profiler to monitor object creation and destruction. I needed them to keep track of destruction. But the approach is out-dated. (It was written in 2004 targeting J2SE 1.4.) Professional profiling tools are much more powerful and reliable and the newer Java 5 features like JMX or agents and JVMTI can be used for that too.
PhantomReferences (always used together with the Reference queue) are superior to finalize which has some problems and should therefore be avoided. Mainly making objects reachable again. This could be avoided with the finalizer guardian idiom (-> read more in 'Effective Java'). So they are also the new finalize.
Furthermore, PhantomReferences
allow you to determine exactly when an object was removed from memory. They
are in fact the only way to determine that. This isn't generally that
useful, but might come in handy in certain very specific circumstances
like manipulating large images: if you know for sure that an image should be
garbage collected, you can wait until it actually is before attempting to
load the next image, and therefore make the dreaded OutOfMemoryError less
likely. (Quoted from enicholas.)
And as psd wrote first, Roedy Green has a good summary of references.
A general diced-up table explanation, from the Java Glossary.
Which of course coincides with the PhantomReference documentation:
Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.
And last but not least, all the gory details (this is a good read): Java Reference Objects (or How I Learned to Stop Worrying and Love OutOfMemoryError).
Happy coding.
(But to answer the question, I've only ever used WeakReferences.)
Great explanation of Phantom Reference usage:
Phantom references are safe way to know an object has been removed
from memory. For instance, consider an application that deals with
large images. Suppose that we want to load a big image in to memory
when large image is already in memory which is ready for garbage
collected. In such case, we want to wait until the old image is
collected before loading a new one. Here, the phantom reference is
flexible and safely option to choose. The reference of the old image
will be enqueued in the ReferenceQueue once the old image object is
finalized. After receiving that reference, we can load the new image
in to memory.
I found a practical and useful use case of PhantomReference which is org.apache.commons.io.FileCleaningTracker in commons-io project. FileCleaningTracker will delete the physical file when its marker object is garbage collected.
Something to take note is the Tracker class which extends PhantomReference class.
THIS SHOULD BE OBSOLETE WITH JAVA 9!
Use java.util.Cleaner instead! (Or sun.misc.Cleaner on older JRE)
Original post:
I found that the use of PhantomReferences has nearly the same amount of pitfalls as finalizer methods (but a fewer problems once you get it right).
I have written a small solution (a very small framework to use PhantomReferences) for Java 8.
It allows to use lambda expressions as callbacks to be run after the object has been removed. You can register the callbacks for inner resources that should be closed.
With this I have found a solution that works for me as it makes it much more practical.
https://github.com/claudemartin/java-cleanup
Here's a small example to show how a callback is registered:
class Foo implements Cleanup {
//...
public Foo() {
//...
this.registerCleanup((value) -> {
try {
// 'value' is 'this.resource'
value.close();
} catch (Exception e) {
logger.warning("closing resource failed", e);
}
}, this.resource);
}
And then there is the even simpler method for auto-close, doing about the same as the above:
this.registerAutoClose(this.resource);
To answer your questions:
[ then whats the use of it ]
You can't clean up something that doesn't exist. But it could have had resources that still exist and need to be cleaned up so they can be removed.
But what is the use of this concept/class?
It's not necessarily to do anything with any effect other than debugging/logging. Or maybe for statistics.
I see it more like a notification service from the GC.
You could also want to use it to remove aggregated data that becomes irrelevant once the object is removed (but there are probably better solutions for that).
Examples often mention database connections to be closed, but I don't see how this is such a good idea as you couldn't work with transactions. An application framework will provide a much better solution for that.
Have you ever used this in any of your project, or do you have any example where we should use this? Or is this concept made just for interview point of view ;)
I use it mostly just for logging. So I can trace the removed elements and see how GC works and can be tweaked. I wouldn't run any critical code in this way. If something needs to be closed then it should be done in a try-with-resource-statement.
And I use it in unit tests, to make sure I don't have any memory leaks. The same way as jontejj does it. But my solution is a bit more general.
I used a PhantomReference in a unit test to verify that the code under test didn't keep unnessecary references to some object. (Original code)
import static com.google.common.base.Preconditions.checkNotNull;
import static org.fest.assertions.Assertions.assertThat;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import com.google.common.testing.GcFinalization;
/**
* Helps to test for memory leaks
*/
public final class MemoryTester
{
private MemoryTester()
{
}
/**
* A simple {#link PhantomReference} that can be used to assert that all references to it is
* gone.
*/
public static final class FinalizationAwareObject extends PhantomReference<Object>
{
private final WeakReference<Object> weakReference;
private FinalizationAwareObject(Object referent, ReferenceQueue<Object> referenceQueue)
{
super(checkNotNull(referent), referenceQueue);
weakReference = new WeakReference<Object>(referent, referenceQueue);
}
/**
* Runs a full {#link System#gc() GC} and asserts that the reference has been released
* afterwards
*/
public void assertThatNoMoreReferencesToReferentIsKept()
{
String leakedObjectDescription = String.valueOf(weakReference.get());
GcFinalization.awaitFullGc();
assertThat(isEnqueued()).as("Object: " + leakedObjectDescription + " was leaked").isTrue();
}
}
/**
* Creates a {#link FinalizationAwareObject} that will know if {#code referenceToKeepTrackOff}
* has been garbage collected. Call
* {#link FinalizationAwareObject#assertThatNoMoreReferencesToReferentIsKept()} when you expect
* all references to {#code referenceToKeepTrackOff} be gone.
*/
public static FinalizationAwareObject createFinalizationAwareObject(Object referenceToKeepTrackOff)
{
return new FinalizationAwareObject(referenceToKeepTrackOff, new ReferenceQueue<Object>());
}
}
And the test:
#Test
public void testThatHoldingOnToAnObjectIsTreatedAsALeak() throws Exception
{
Object holdMeTight = new String("Hold-me-tight");
FinalizationAwareObject finalizationAwareObject = MemoryTester.createFinalizationAwareObject(holdMeTight);
try
{
finalizationAwareObject.assertThatNoMoreReferencesToReferentIsKept();
fail("holdMeTight was held but memory leak tester did not discover it");
}
catch(AssertionError expected)
{
assertThat(expected).hasMessage("[Object: Hold-me-tight was leaked] expected:<[tru]e> but was:<[fals]e>");
}
}
It is common to use WeakReference where PhantomReference is more appropriate. This avoids certain problems of being able to resurrect objects after a WeakReference is cleared/enqueued by the garbage collector. Usually the difference doesn't matter because people are not playing silly buggers.
Using PhantomReference tends to be a bit more intrusive because you can't pretend that the get method works. You can't, for example, write a Phantom[Identity]HashMap.
I used it in the early days of Android. Back them a BitmapDrawable had an underlying Bitmap that used memory that was not allocated in the Java Heap space, which meant that you were using memory, but the JVM didn't feel the memory pressure. The symptom was the app would crash by running out of memory, but you'd never find that your finalizer was called (or that there hadn't been a garbage collection sweep at all).
So I created a subclass of PhantomReference that had a hard reference to the Bitmap (class variable). The PhantomReference itself pointed to the BitmapDrawable.
When the phantom reference would come off the queue indicating that the BitmapDrawable was no longer reachable, I'd call the release method on the Bitmap which released the memory that was outside of the vm heap space.
It worked great, it more or less completely removed the out of memory failures that occurred because of that weird memory model on early Android.
Android later changed the memory model to load bitmaps into the JVM heap, btw, because you actually want your vm to feel memory pressure if the app is running out of memory. It was definitely a "Black Diamond" situation to have to release the memory like this and I doubt most app developers realized that Garbage Collection wasn't going to help them because the memory was outside the view of the Garbage Collector. They probably just viewed it as an Android bug.
if you use its get() method it will always return null, and not the
object. [ then whats the use of it ]
The useful methods to call (rather than get()) would be isEnqueued() or referenceQueue.remove(). You would call these methods to perform some action that needs to take place on the final round of garbage collection of the object.
The first time around is when the object has its finalize() method called, so you could put closing hooks there too. However, as others have stated, there are probably more sure ways of performing clean up or whatever action needs to take place pre and post garbage collection or, more generally, upon end-of-life of the object.
I found another practical use of PhantomReferences in LeakDetector class of Jetty.
Jetty uses LeakDetector class to detect if the client code acquires a resource but never releases it and the LeakDetector class uses the PhantomReferences for this purpose.
Here is a generic example of using it: In this case, for some Swing code in a vector editor, where it's easy to create tens of thousands of AffineTransform instances inside the paint loop, when they are easily recycled and reused, and this showed itself to be a significant bottleneck in profiling. I've used the same pattern to reuse CharBuffer instances when processing log files line-by line. Basically the pattern is: You have some data structure which is expensive to create, and it is one you can completely reset the state on, rather than create a new one every time. So, you create a PhantomReference subclass that strongly references the object you want to recycle and reuse, whose referent is a thing that could be referencing the object; to track when it is safe to recycle an object, you either
Return a facade for the object, that implements the same interface or something close enough (e.g. a CharSequence implementation that wraps a CharBuffer), and use that as the referent of your PhantomReference or
Callers pass you a reference to themselves and so you can recycle an object when the caller goes out of scope
In other words, the pattern here you're asking the queue to tell you when every object that could know about some cached thing is gone, so you can make it available for reuse to another caller.

Assigning "null" to objects in every application after their use

Do you always assign null to an object after its scope has been reached?
Or do you rely on the JVM for garbage collection?
Do you do it for all sort of applications regardless of their length?
If so, is it always a good practice?
It's not necessary to explicitly mark objects as null unless you have a very specific reason. Furthermore, I've never seen an application that marks all objects as null when they are no longer needed. The main benefit of garbage collection is the intrinsic memory management.
no, don't do that, except for specific cases such as static fields or when you know a variable/field lives a lot longer than the code referencing it
yes, but with a working knowledge of your VM's limits (and how to cause blocks of memory to be held accidentally)
n/a
I declare almost all of my variables as "final". I also make my methods small and declare most variables local to methods.
Since they are final I cannot assign them null after use... but that is fine since the methods are small the objects are eligible for garbage collection once they return. Since most of the variables are local there is less chance of accidentally holding onto a reference for longer than needed (memory leak).
Assignin null to a variable does not implicitly mean it will be garbage collected right away. In fact it most likely won't be. Whether you practice setting variables to null is usually only cosmetic (with the exception of static variables)
We don't practice this assigning "null". If a variable's scope has reached it's end it should already be ready for GC. There may be some edge cases in which the scope lasts for a while longer due to a long running operation in which case it might make sense to set it to null, but I would imagine they would be rare.
It also goes without saying that if the variable is an object's member variable or a static variable and hence never really goes out of scope then setting it to null to GC is mandatory.
Garbage collection is not as magical as you might expect. As long as an object is referenced from any reachable object it simply can't be collected. So it might be absolutely necessary to null a reference in order to avoid memory leaks. I don't say you should do this always, but always when it's necessary.
As the others have mentioned, it's not usually necessary.
Not only that, but it clutters up your code and increases the data someone needs to read and understand when revisiting your code.
Assigning is not done to objects, it is done to variables, and it means that this variable then holds a reference to some object. Assigning NULL to a variable is not a way to destroy an object, it just clears one reference. If the variable you are clearing will leave its scope afterwards anyway, assigning NULL is just useless noise, because that happens on leaving scope in any case.
The one time I tend to use this practice is if I need to transform a large Collection in some early part of a method.
For example:
public void foo() {
List<? extends Trade> trades = loadTrades();
Map<Date, List<? extends Trade>> tradesByDate = groupTradesByDate(trades);
trades = null; // trades no longer required.
// Apply business logic to tradesByDate map.
}
Obviously I could reduce the need for this by refactoring this into another method: Map<Date, List<? extends Trade>>> loadTradesAndGroupByDate() so it really depends on circumstances / clarity of code.
I only assign a reference to null when:
The code really lies in a memory-critical part.
The reference has a wide scope (and must be reused later). If it is not the case I just declare it in the smallest possible code block. It will be available for collection automatically.
That means that I only use this technique in iterative process where I use the reference to store incoming huge collection of objects. After processing, I do not need the collection any more but I want to reuse the reference for the next collection.
In that case (and only in that case), I then call System.gc() to give a hint to the Garbage Collector. I monitored this technique through heap visualizer and it works very well for big collections (more then 500Mb of data).
When using the .Net I don't think there's a need to set the object to null. Just let the garbage collection happen.
- Do you always assign null to an object after its scope has been reached?
No
- Or do you rely on the JVM for garbage collection?
Yes
- Do you do it for all sort of applications regardless of their length?
Yes
- If so, is it always a good practice?
N/A
I assume you're asking this question because you've seen code with variables being assigned to null at the point where they will never be accessed again.
I dislike this style, but another programmer used it extensively, and said he was taught to do so at a programming course at his university. The reasoning he gave is that it would prevent undetectable bugs if he tried to reuse the variable later on, instead of indeterminate behavior, he'd get a null pointer exception.
So if you're prone to using variables where you shouldn't be using variables, it might make your code more easy to debug.
There was a class of memory leak bugs that happened regardless of whether I set the reference to null - if the library I was using was written in a language like C without memory management, then simply setting the object to null would not necessarily free the memory. We had to call the object's close() method to release the memory (which, of course, we couldn't do after setting it to null.)
It thus seems to me that the de facto method of memory management in java is to rely on the garbage collector unless the object/library you're using has a close() method (or something similar.)

Does setting Java objects to null do anything anymore?

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?
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.
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.
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.
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.
Firstly, It does not mean anything that you are setting a object to null. I explain it below:
List list1 = new ArrayList();
List list2 = list1;
In above code segment we are creating the object reference variable name list1 of ArrayList object that is stored in the memory. So list1 is referring that object and it nothing more than a variable. And in the second line of code we are copying the reference of list1 to list2. So now going back to your question if I do:
list1 = null;
that means list1 is no longer referring any object that is stored in the memory so list2 will also having nothing to refer. So if you check the size of list2:
list2.size(); //it gives you 0
So here the concept of garbage collector arrives which says «you nothing to worry about freeing the memory that is hold by the object, I will do that when I find that it will no longer used in program and JVM will manage me.»
I hope it clear the concept.
One of the reasons to do so is to eliminate obsolete object references.
You can read the text here.

Categories