Better late than never.
This is not how weak references work. The WeakReference
-object will always be there, but its get()
-method may return the original object or null
(if the original object was GC:ed).
This means your Stack will always contain a WeakReference
-object.
Here's a verbose test I did (however it depends on the JVM doing GC in the middle, which may or may not happen "on command" - try to add some more System.gc()
:s if it doesn't happen):
public static void main(String[] args) {
// Set up
Object object = new Object();
final WeakReference<Object> weakReference = new WeakReference<>(object);
final Stack<WeakReference<Object>> references = new Stack<>();
references.add(weakReference);
// Before
System.out.println("Before:");
references.forEach(r -> {
System.out.println("Reference: " + r);
System.out.println("Object: " + r.get());
});
// GC
object = null;
System.gc();
System.gc();
System.gc();
// After
System.out.println("After:");
references.forEach(r -> {
System.out.println("Reference: " + r);
System.out.println("Object: " + r.get());
});
}
The output:
Before:
Reference: java.lang.ref.WeakReference@238e0d81
Object: java.lang.Object@31221be2
After:
Reference: java.lang.ref.WeakReference@238e0d81
Object: null
Your best approach is probably to just ignore entries where get()
returns null
once you "pop" them.
Side note: My first test was with a String-object, which never got GC:ed. This is because strings in Java are "interned" (see String.intern()
) meaning there is a hidden cache of static strings that are reused. A string will never be GC:ed, unless that pool of strings are full (or something along that line...) I think strings are the only Java object with this "special" characteristic but I'd recommend always using custom made objects in a WeakReference to make sure it gets GC:ed correctly.