Say i have a static queue in class A.
I instantiate class B and in the constructor I instantiate an object of
class A just to get a reference of the static queue.
Once the constructor finishes there is no reference to any object of
class A, just it's queue.
Later on I instatiate several objects of class A that will all add to
the queue.
So the question is:
if I don't have a reference to any object of class A, but I have a
reference to it's static queue, will the "lost" reference to class A I
used in the constructor be collected by the garbage collector? If yes
once a new object is constructed will the static queue have the same
address, or will a new address be given to it?
And if the address is the same, but the "lost" reference is not
collected can I take care of that memory leak, and keep the reference of
the static queue?
> Say i have a static queue in class A.
>
[quoted text clipped - 18 lines]
> collected can I take care of that memory leak, and keep the reference of
> the static queue?
As long as you keep a reference to the static member, it will not be
garbage collected. The class A obects and how they get garbage
collected may depend on the implementation of Java. As long as you
lett go of references properly, garbage collection should work.
-Missaka
Remon van Vliet - 04 May 2006 10:22 GMT
>> Say i have a static queue in class A.
>>
[quoted text clipped - 25 lines]
>
> -Missaka
No, the object referenced to by a static field will never be garbage
collected. The object that's referred to might, if the static reference is
replaced with a reference to another object. But the instance of the queue
assigned to the static field will not be garbage collected at any time.
Garbage collection occurs if, and only if, no active thread can access the
object in any way. Once the GC realizes that, the finalize() method of said
object is called, if after that call the object is still not referenced
(which might not be the case if the object is ressurected in the finalize()
method or if the finalize() method threw an exception) it is disposed.
There is actually one situation where it *might* be garbage collected.
Imagine the following class :
public class StaticGC() {
private static Queue queue = new LinkedList();
// possibly more methods that do nothing with the queue and provide no
access to it in any way
}
I cant think of a way that would grant access to the queue instance in any
way to living threads so you could assume it can be garbage collected. That
said i sincerely doubt that happens, feel free to test it.
- Remon van Vliet
> if I don't have a reference to any object of class A, but I have a
> reference to it's static queue, will the "lost" reference to class A I
> used in the constructor be collected by the garbage collector? If yes
> once a new object is constructed will the static queue have the same
> address, or will a new address be given to it?
Unfortunately the answer is rather context-dependent. In 99% of cases the
answer is simple, but you /can/ create cases where the answer is more
complicated if you try hard enough.
In most cases, the simple answer will be correct: As long as class B is loaded
into the JVM then class A will be too, and so the queue in A will continue to
exist whether or not B keeps a reference to it. For "normal" Java programs
both A and B will be loaded for the entire lifetime of the program. So, once
the queue has been created, it will never go away again (unless you explicitly
set the static reference in A to null).
The non-simple answer applies in specialised circumstances, and /only/ applies
if someone is using custom classloaders. Unfortunately "advanced" application
frameworks (such as servlet containers, etc) /do/ make use of classloaders.
Anyway, in the more complicated case, there are again two possibilities: a
simple one which applies in nearly all cases, and a complicated one which
applies if you try hard enough.
If A and B are loaded by the same classloader, or if A is loaded by a parent of
B's classloader (which will /always/ be the case if the code in B refers to A
directly, rather than using Class.forName()), then A will live at least as long
as B. So in that case the picture is pretty-much the same as for the simple
case, except that it may be possible for both A and B to be unloaded before the
program exits (and so the queue will be discarded and cleaned up -- but that
won't usually matter because there is no longer any need for it).
The last case is most complicated, but /cannot/ apply unless you yourself are
playing games with classloaders. If the code for B does not contain any direct
references to A (no variables declared as type A, for instance), /and/ if
you've taken care to load A through a classloader which is not the one used for
B (or one of its parents), then it is possible for A to be unloaded while B is
still active. If so, then the queue will be discarded when A unloads (assuming
B has no reference to it), and if B repeats the operations it used to get a
reference to the queue the first time, then it is possible that it will see a
new queue associated with a freshly re-loaded and re-initialised version of
class A.
I hope that's not overcomplicating what you thought was a simple question. As
I say, in nearly all cases, you can treat static variables as having a lifetime
when extends to program exit.
-- chris
Ben - 04 May 2006 13:51 GMT
Thanks for the info, it helps. Since I'm not messing with classloaders,
it's going to be pretty straight forward for me, and I won't have to
worry about it. Thanks again.
Ben
Adam Maass - 06 May 2006 06:28 GMT
>> if I don't have a reference to any object of class A, but I have a
>> reference to it's static queue, will the "lost" reference to class A I
[quoted text clipped - 68 lines]
>
> -- chris
Chris, thanks for this thorough and clear explanation. I was going to try to
put one together, but gave up in frustration.
-- Adam Maass