Excerpted from: https://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html
A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory. Weak references allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have to do it yourself. You create a weak reference like this:
WeakReference<Widget> weakWidget = new WeakReference<Widget>(widget);
and then elsewhere in the code you can use weakWidget.get()
to get the actual Widget
object. Of course the weak reference isn't strong enough to prevent garbage collection, so you may find (if there are no strong references to the widget) that weakWidget.get()
suddenly starts returning null
.
WeakHashMap
works exactly like HashMap
, except that the keys (not the values!) are referred to using weak references. If a WeakHashMap
key becomes garbage, its entry is removed automatically. If you're following the standard convention of referring to your maps via the Map
interface, no other code needs to even be aware of the change and requires no changes other than the switch fromHashMap
to a WeakHashMap
.
Difference degrees of Weakness
- Soft references -
- Phantom references - A phantom reference is quite different than either
SoftReference
orWeakReference
. Its grip on its object is so tenuous that you can't even retrieve the object -- itsget()
method always returnsnull
. The only use for such a reference is keeping track of when it gets enqueued into aReferenceQueue
, as at that point you know the object to which it pointed is dead.PhantomReferences
are enqueued only when the object is physically removed from memory, and theget()
method always returnsnull
specifically to prevent you from being able to "resurrect" an almost-dead object. Uses: - Phantom references allow you to determine exactly when an object was removed from memory. They are in fact the only way to determine that. This isn't generally that useful, but might come in handy in certain very specific circumstances like manipulating large images: if you know for sure that an image should be garbage collected, you can wait until it actually is before attempting to load the next image, and therefore make the dreaded
OutOfMemoryError
less likely. PhantomReferences
avoid a fundamental problem with finalization:finalize()
methods can "resurrect" objects by creating new strong references to them. Well, the problem is that an object which overridesfinalize()
must now be determined to be garbage in at least two separate garbage collection cycles in order to be collected. When the first cycle determines that it is garbage, it becomes eligible for finalization. Because of the (slim, but unfortunately real) possibility that the object was "resurrected" during finalization, the garbage collector has to run again before the object can actually be removed. And because finalization might not have happened in a timely fashion, an arbitrary number of garbage collection cycles might have happened while the object was waiting for finalization. This can mean serious delays in actually cleaning up garbage objects, and is why you can getOutOfMemoryErrors
even when most of the heap is garbage. WithPhantomReference
, this situation is impossible -- when aPhantomReference
is enqueued, there is absolutely no way to get a pointer to the now-dead object (which is good, because it isn't in memory any longer). BecausePhantomReference
cannot be used to resurrect an object, the object can be instantly cleaned up during the first garbage collection cycle in which it is found to be phantomly reachable. You can then dispose whatever resources you need to at your convenience.
A soft reference is exactly like a weak reference, except that it is less eager to throw away the object to which it refers. An object which is only weakly reachable (the strongest references to it are WeakReferences
) will be discarded at the next garbage collection cycle, but an object which is softly reachable will generally stick around for a while.
SoftReferences
aren't required to behave any differently than WeakReferences
, but in practice softly reachable objects are generally retained as long as memory is in plentiful supply. This makes them an excellent foundation for a cache for the use case of image caching described below for instance.
Suppose you have an application which has to work with user-supplied images. Naturally you want to cache these images, because loading them from disk is very expensive and you want to avoid the possibility of having two copies of the (potentially gigantic) image in memory at once.
Because an image cache is supposed to prevent us from reloading images when we don't absolutely need to, you will quickly realize that the cache should always contain a reference to any image which is already in memory. With ordinary strong references, though, that reference itself will force the image to remain in memory, which requires you (just as above) to somehow determine when the image is no longer needed in memory and remove it from the cache, so that it becomes eligible for garbage collection. Once again you are forced to duplicate the behavior of the garbage collector and manually determine whether or not an object should be in memory.
No comments:
Post a Comment