[ACCEPTED]-When would you use a WeakHashMap or a WeakReference?-weak-references
One problem with strong references is caching, particular 24 with very large structures like images. Suppose 23 you have an application which has to work with 22 user-supplied images, like the web site 21 design tool I work on. Naturally you want 20 to cache these images, because loading 19 them from disk is very expensive and you 18 want to avoid the possibility of having 17 two copies of the (potentially gigantic) image 16 in memory at once.
Because an image cache 15 is supposed to prevent us from reloading 14 images when we don't absolutely need to, you 13 will quickly realize that the cache should always 12 contain a reference to any image which 11 is already in memory. With ordinary strong 10 references, though, that reference itself 9 will force the image to remain in memory, which requires 8 you to somehow determine when the image 7 is no longer needed in memory and remove 6 it from the cache, so that it becomes 5 eligible for garbage collection. You are 4 forced to duplicate the behavior of the 3 garbage collector and manually determine whether 2 or not an object should be in memory.
Understanding Weak References, Ethan 1 Nicholas
WeakReference
versus SoftReference
One distinction to be clear on is the difference 12 between a WeakReference
and a SoftReference
.
Basically a WeakReference
will be GC-d by 11 the JVM eagerly, once the referenced object 10 has no hard references to it. A SoftReference
d object on 9 the other hand, will tend to be left about 8 by the garbage collector until it really 7 needs to reclaim the memory.
A cache where 6 the values are held inside WeakReference
s would be pretty useless 5 (in a WeakHashMap
, it is the keys which are weakly 4 referenced). SoftReferences
are useful to wrap the values 3 around when you want to implement a cache 2 which can grow and shrink with the available 1 memory.
One Common use of WeakReference
s and WeakHashMap
s in particular 21 is for adding properties to objects. Occasionally 20 you want to add some functionality or data 19 to an object but subclassing and/or composition 18 are not an option in that case the obvious 17 thing to do would be to create a hashmap 16 linking the object you want to extend to 15 the property you want to add. then whenever 14 you need the property you can just look 13 it up in the map. However, if the objects 12 you are adding properties to tend to get 11 destroyed and created a lot, you can end 10 up with a lot of old objects in your map 9 taking up a lot of memory.
If you use a WeakHashMap
instead 8 the objects will leave your map as soon 7 as they are no longer used by the rest of 6 your program, which is the desired behavior.
I 5 had to do this to add some data to java.awt.Component
to get 4 around a change in the JRE between 1.4.2 3 and 1.5, I could have fixed it by subclassing 2 every component I was interested int (JButton
, JFrame
, JPanel
....) but 1 this was much easier with much less code.
Another useful case for WeakHashMap
and WeakReference
is a listener registry implementation.
When 22 you create something which wants to listen 21 to certain events, usually you register 20 a listener, e.g.
manager.registerListener(myListenerImpl);
If the manager
stores your listener 19 with a WeakReference
, that means you don't need to remove 18 the register e.g. with a manager.removeListener(myListenerImpl)
because it will 17 be automatically removed once your listener 16 or your component holding the listener becomes 15 unavailable.
Of course you still can manually 14 remove your listener, but if you don't or you 13 forget it, it will not cause a memory leak, and 12 it will not prevent your listener being 11 garbage collected.
Where does WeakHashMap
come into the picture?
The listener registry 10 which whishes to store registered listeners 9 as WeakReference
s needs a collection to store these references. There 8 is no WeakHashSet
implementation in the standard Java 7 library only a WeakHashMap
but we can easily use the 6 latter one to "implement" the functionality 5 of the first one:
Set<ListenerType> listenerSet =
Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
With this listenerSet
to register 4 a new listener you just have to add it to 3 the set, and even if it is not removed explicitly, if 2 the listener is no longer referenced, it 1 will be removed automatically by the JVM.
This blog post demonstrates the use of both 11 classes: Java: synchronizing on an ID. The usage goes something like 10 this:
private static IdMutexProvider MUTEX_PROVIDER = new IdMutexProvider();
public void performTask(String resourceId) {
IdMutexProvider.Mutex mutext = MUTEX_PROVIDER.getMutex(resourceId);
synchronized (mutext) {
// look up the resource and do something with it
}
}
IdMutextProvider provides id-based 9 objects to synchronize on. The requirements 8 are:
- must return a reference to the same object for concurrent use of equivalent IDs
- must return a different object for different IDs
- no release mechanism (objects are not returned to the provider)
- must not leak (unused objects are eligible for garbage collection)
This is achieved using an internal storage 7 map of type:
WeakHashMap<Mutex, WeakReference<Mutex>>
The object is both key and value. When 6 nothing external to the map has a hard reference 5 to the object, it can be garbage collected. Values 4 in the map are stored with hard references, so 3 the value must be wrapped in a WeakReference to prevent 2 a memory leak. This last point is covered 1 in the javadoc.
If you for example want to keep track of 6 all objects created of a certain class. To 5 still allow these objects to be garbage 4 collected, you keep a list/map of weak references 3 to the objects instead of the objects themselves.
Now 2 if someone could explain phantom-references 1 to me, I'd be happy...
As stated above, weak reference are held 17 for as long as a strong reference exists.
An 16 example usage would be to use WeakReference 15 inside listeners, so that the listeners 14 are no longer active once the main reference 13 to their target object is gone. Note that 12 this does not mean the WeakReference is 11 removed from the listeners list, cleaning 10 up is still required but can be performed, for 9 example, at scheduled times. This has also 8 the effect of preventing the object listened 7 to from holding strong references and eventually 6 be a source of memory bloat. Example: Swing 5 GUI components refering a model having a 4 longer lifecycle than the window.
While playing 3 with listeners as described above we rapidly 2 realised that objects get collected "immediately" from 1 a user's point of view.
One real world use I had for WeakReferences 9 is if you have a single, very large object 8 that's rarely used. You don't want to keep 7 it in memory when it's not needed; but, if 6 another thread needs the same object, you 5 don't want two of them in memory either. You 4 can keep a weak reference to the object 3 somewhere, and hard references in the methods 2 that use it; when the methods both finish, the 1 object will be collected.
I did a google code search for "new 2 WeakHashMap()".
I got a bunch of matches 1 from the GNU classpath project and
- Apache xbean Project : WeakHashMapEditor.java
- Apache Lucene project : CachingWrapperFilter.java
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.