To understand when an object will be garbage collected, you need to understand a bit about how objects are allocated.
All programs have two parts of memory; the stack and the heap. As the program executes, it will enter new functions or methods - this creates a new scope. Whenever a new scope is created, a corresponding new 'frame' is placed on 'top' of the stack. This frame has references to all the variables being used in that scope.
When an object is created, such as via the new
keyword (MyObject obj = new MyObject();
), a part of memory is set aside on the heap for that object to occupy. The current stack frame will then have a reference to where in the heap the object is living.
That object, obviously, may have references to other objects on the heap. The way the program knows how to get to these objects is by moving from the reference on the stack to the first object on the heap, and then to any other objects connected directly or indirectly. All these objects are on the heap.
When the stack frame is unloaded (which happens when the program leaves that scope), any references held by that frame are released. This may mean that one or more objects on the heap no longer are referenced either directly or indirectly by anything on the stack. These are the objects that are available for garbage collection. If you want to know whether an object will be garbage collected, you simply have to ask whether it is currently connected to the stack.
Note that such objects are available for garbage collection, not automatically garbage collected. Any objects so marked will be torn down at a time of the collector's choosing. Possibly never. finalize()
is run on any object being collected: this can ensure certain things happen when it's collected, but given that you can't guarantee it ever is, the usefulness is limited.
Now, for an example:
public void A() {//entering this method creates a new stack frame
MyObject obj = new MyObject();//'obj' is a reference belonging to the current stack frame.
//the obj reference is now pointing to a place in memory on the heap
this.B();
}
public void B() { //Now we are in a new stack frame on top of the older one.
obj.doSomething();//Doesn't work! There is no 'obj' reference in this stack frame
//This results in a null pointer exception
MyObject obj2 = new MyObject();//A totally new object is created on the heap!
} //When we leave this method we leave the scope, and the stack frame.
//obj2 is no longer referenced, and so is available for garbage collection
One final note; let us say you instantiate three objects; A
, B
, and C
. C
is passed to A
and B
and saved as a member variable of those objects. Now lets say that you leave the scope where B
is defined. C
is not garbage collected, because A
still has a reference to it; there is still some place on the stack that is holding on to something that is holding on to C
.