I'm confused with this program:
class Point {
private final int x;
private final int y;
}
public class App
{
WeakReference<Point> newPoint() {
Point referent = new Point();
return new WeakReference<Point>(referent); // after return, stack parameter referent is invalid.
}
public static void main( String[] args ) {
App a = new App();
WeakReference<Point> wp = a.newPoint(); // wp is hold valid or invalid reference?
System.out.println(wp.get()); // not null
}
}
I knew that if weak reference is pointing to an object that's no longer alive, its get() should return null. But in my code, seems its still alive.
Where did I get wrong?
Your understanding is imprecise, especially where it relies on the idea of aliveness.
Referenceobjects in general andWeakReferenceobjects in particular are not directly concerned with any of the senses of aliveness that I recognize. Rather, they are concerned with reachability.The API docs for
java.lang.Reference#get()(which is not overridden byWeakReference) say this:Note well that the condition for
get()returningnullis rather specific: the reference object has been cleared. This is achieved for a given instance by invoking that instance'sclear()method. As the doc indicates, this may be done by the garbage collector or by the application.Among the key differences between
Referencesubclasses is the conditions under which the garbage collector will perform such clearing. ForWeakReferences, the API docs say:Thus, until the garbage collector determines that a given object is (only) weakly reachable, it will not clear weak references to that object. The garbage collector probably does not run at all during the brief run of your small program, and if it did run, it would be surprising for it to be timed correctly to observe the
Pointin question to be weakly reachable before the reference'sget()method is invoked.You could try forcing a GC run by invoking
System.gc()at the appropriate place. I anticipate that doing so will result in the weak reference being cleared. That would be for demonstrative purposes only, however. Generally speaking, you should rely on Java to perform GC when appropriate, not force it.