Re: more on SoftReference, WeakReference and PhantomReference
"Richard O. Hammer" <[email protected]>
| Newsgroups | gmane.org.user-groups.trijug.juglist |
|---|---|
| Message-ID | <[email protected]> |
I doubt you can be sure that a call to System.gc() will run a garbage
collector. It's been five years since I read much about this, but I
recall that in the time of Java 1.2 a JVM was not even required to have
a garbage collector. (This was supported with the story that some small
devices may do their Java jobs without needing to collect garbage.)
I think I remember that Javadoc for System.gc() was vague back then,
discouraging a developer from relying upon a call to System.gc(). But
for recent Java releases the Javadoc gives what almost sounds like a
promise:
"When control returns from the method call, the Java Virtual Machine has
made a best effort to reclaim space from all discarded objects."
I've used WeakReference(s) for mail-message objects in a mailserver. In
this application I'd like to keep the object in memory if possible, to
lessen database traffic, because sometimes the object will be needed
again in a short time (perhaps 2 seconds, for a retry if a first attempt
to send fails).
In the mail-message objects, I use finalize() to write a log message
which verifies that garbage collection is working (on its schedule,
whatever that is).
public void finalize(){
//log the finalization of this message
}
Rich Hammer
Harold Meder wrote:
> OK. What happens if I am working with an object that I got from a weak
> reference when the garbage collector comes around?
>
> No problem: To work with the object, you need to ask the weak reference
> for a strong reference. It is with this strong reference that you can
> work with it. So, even though everyone else has giving up their strong
> reference, the object survives since you still have a strong reference.
>
> So, when do you actually give up your strong reference? Phillip says,
> "Try it!"
>
> You better set your strong reference = null.
> Just going out of scope is not enough.
>
> Your strong reference stays on your stack until it is overwritten.
>
> That means that any thread's stack can hold a strong reference that you
> thought has long gone out of scope. The garbage collector will not
> collect it until the stack is overwritten.
>
> This might suggest that a pooled thread can hold strong references on
> its stack until it is started up again and overwrites its stack. Or is
> a thread's stack garbage collected when it stops? I will let someone
> else try it.
>
> Note that this stowaway strong reference hiding on your stack may be a
> Collection containing thousands of strong references preventing the
> garbage collector from doing what you might think it should have done a
> long time ago.
>
> This problem is independent of the use of weak references. This is a
> problem that is happening in your code … if you don't set your (strong)
> references to = null.
>
> Aren't you ashamed of pointing out that there was no need to set
> references = null before they go out of scope?
>
> The appended code produces the following output.
>
> ----------
>
> Both Weak References survive while Strong References survive on stack.
> (1)111, 222
> Can't garbage collect it while it has a strong reference.
> (100) 111, 222
> Can't garbage collect, even when it Strong Reference goes out of scope.
> (100) 111, 222
> Can garbage collect, when Strong Reference set to null.
> (1) 111, null
> At last! If the stack is overwritten, the last Strong Reference is gone.
> (1) null, null
>
> ----------
>
> import java.lang.ref.WeakReference;
>
> public class RefTest
> {
> public static void main (String[] args)
> {
> WeakReference <Integer> wr1;
> WeakReference <Integer> wr2;
> {
> Integer obj1 = new Integer (111);
> Integer obj2 = new Integer (222);
> wr1 = new WeakReference <Integer> (obj1);
> wr2 = new WeakReference <Integer> (obj2);
> }
> // obj is out of scope,
> // but the garbage collector is lazy.
> System.gc (); Thread.yield ();
> System.out.println (
> "Both Weak References survive " +
> "while Strong References survive on stack.\n(1)" +
> wr1.get () + ", " + wr2.get ());
>
> int i = 0;
> Integer newStrongRef2;
> {
> // Before we loose the objects,
> // let's save them with new Strong Referenences.
> Integer newStrongRef1 = wr1.get ();
> newStrongRef2 = wr2.get ();
> while (wr1.get () != null)
> {
> System.gc (); Thread.yield ();
> if ( ++i > 99) break;
> }
> System.out.println (
> "Can't garbage collect it while it has a strong reference.\n("
> + i + ") " +
> wr1.get () + ", " + wr2.get ());
> }
>
> i = 0;
> {
> // OK, with newStrongRef1 out of scope,
> // but
> while ( wr1.get () != null)
> {
> System.gc (); Thread.yield ();
> if ( ++i > 99) break;
> }
> System.out.println (
> "Can't garbage collect, " +
> "even when it Strong Reference goes out of scope.\n("
> + i + ") " +
> wr1.get () + ", " + wr2.get ());
>
> i = 0;
> newStrongRef2 = null;
> {
> // OK, with newStrongRef1 out of scope,
> // but
> while (wr2.get () != null)
> {
> System.gc (); Thread.yield ();
> if ( ++i > 99) break;
> }
> System.out.println (
> "Can garbage collect, " +
> "when Strong Reference set to null.\n("
> + i + ") " +
> wr1.get () + ", " + wr2.get ());
> }
> }
>
> Integer obj3 = new Integer(333);
> i = 0;
> {
> while (wr1.get () != null)
> {
> System.gc (); Thread.yield ();
> if ( ++i > 999) break;
> }
> System.out.println (
> "At last! If the stack is overwritten, " +
> "the last Strong Reference is gone.\n("
> + i + ") " +
> wr1.get () + ", " + wr2.get ());
> }
> }
>
> }