A weak pointer
(or a weak reference, as "reference" is a more abstract term for "pointer" that is not limited to a specific language) is a pointer which, in a system utilizing GarbageCollection
, doesn't contribute to the liveness of the object it points to. In other words, if an object is accessible from the root set only through one or more paths each containing a weak pointer, it is considered garbage and may be reclaimed by the collector.
(A normal pointer, which does contribute to the liveness of an object and which is traversed by the collector, is sometimes called a StrongPointer?
in order to distinguish it from a weak pointer. If a pointer is described as neither weak nor strong, consider it strong).
Weak pointers should have the property that if the object they are pointing to is recycled, any attempt to dereference the now-dead object through the weak pointer (or to assign it to a strong pointer) should fail with an exception. (In other words, WeakPointer
s shouldn't become WildPointer
supports weak pointers--the mechanism by which it does so is truly scary. Why?
One interesting question is whether or not assignment from a weak pointer to a strong pointer should be allowed. The issue of assigning invalid weak pointers mentioned above is one problem. A potentially nastier problem is this:
- An object is created, references are made to it--including one or more weak pointers.
- At some point in the future, the weak pointer becomes the only live pointer pointing to the object--the object is thus dead from the point of view of the GC, and may be recycled.
- Someone then assigns the weak pointer to a strong pointer.
A race condition incurs--after the second step, the object is eligible for garbage collection. However, it may or may not have been collected by step 3. If it was, the assignment should fail; if not, something that was garbage may become alive again. (It is also possible that some other
object referred to by this particular object was collected. Many garbage collectors assume "once garbage, always garbage" and aren't picky about the order in which dead objects are recycled.)
The java WeakReference
class takes all this into account. The basic operation on a FooReference?
is get(), which either returns the pointer, or (if the reference has been "cleared") returns a null. If you call get() and get the pointer back, then because that pointer is "held" by a currently running thread, the object becomes "strongly reachable" for so long as it is on the stack. Weak references are not cleared if they point to strongly reachable objetcs.
In general, the reference gear guarantees that *all* weak references to a given object are cleared at the same time, That from the POV of all
threads this is an atomic operation, that this happens only after the object has been finalised, and after all soft and hard references are cleared. When a Weak reference is cleared, the object it was pointing to is gone
- there is no possible way
of recovering it. That's the whole point.
To do funky stuff, you extend the weak reference object itself, and use a reference queue.
A Soft refernce is different altogether. Soft references may be cleared at any time and in any order, however the understanding is that the GC will not do so unless it starts running short of memory. Weak references, by contrast, are cleared agressively.
In a different scenario a weak pointer is used between an observer object (a view) and an observable object (a container). A weak pointer decouples the two objects from each other. Typically a container is related to an observer by a 1-to-many relation. That is, an observable object is referenced by 1 or more observers. Obviously an observer must keep a reference to the object being observed. Since an observer needs to be notified when the container is changed, a backward reference must also be kept. This is a special case where a cyclic dependency (see: CyclicDependency
) is created. In designs where the objects are reference-counted and deleted when the count drops to zero, this cyclic dependency translates into a resource leak; since neither can be safely deleted. Furthermore, an observer is a dynamic and short-lived object, vs. the lifetime of a container.
A weak pointer is used in such a case to loosen the ties between the two. A weak pointer (or weak reference, as it is sometimes called) is used to reference the observer. When an observable object is to notify its observer(s), it messages the weak pointer for the actual reference. If a null-pointer is returned, then the observer is gone and no notification is needed. At this point the observable can delete the weak pointer. Otherwise, the temporary reference is used to notify the observer that the contents of the container is changed.
The Mozilla Browser (http://www.mozilla.org
) utilizes such a weak pointer. The reader is ecouraged to read the Mozilla project documentation for a more in-depth coverage of the WeakPointer
See Also: ObserverPattern