WeakHashMap, androidweakhashmap
WeakHashMap: when there is no reference to the key except for its own reference, the map will automatically discard this value.
Code
In this example, two Map objects are declared. One is HashMap and the other is WeakHashMap. At the same time, two objects a and B are put into the two maps. remove a and point a and B to null, a in WeakHashMap will be automatically recycled. The reason for this is that for object a, when HashMap. after removing and pointing a to null, in addition to saving a in WeakHashMap, there is no pointer to a, so WeakHashMap will automatically discard, although object B points to null, there is still a pointer to B in HashMap, so WeakHashMap will keep it.
public class Test { public static void main(String[] args) throws Exception { String a = new String("a"); String b = new String("b"); Map weakmap = new WeakHashMap(); Map map = new HashMap(); map.put(a, "aaa"); map.put(b, "bbb"); weakmap.put(a, "aaa"); weakmap.put(b, "bbb"); map.remove(a); a=null; b=null; System.gc(); Iterator i = map.entrySet().iterator(); while (i.hasNext()) { Map.Entry en = (Map.Entry)i.next(); System.out.println("map:"+en.getKey()+":"+en.getValue()); } Iterator j = weakmap.entrySet().iterator(); while (j.hasNext()) { Map.Entry en = (Map.Entry)j.next(); System.out.println("weakmap:"+en.getKey()+":"+en.getValue()); } } }I am the dividing line of tiantiao
WeakHashMap uses the expungeStaleEntries function to automatically release memory by removing unnecessary internal entries. basically, you only need to access the WeakHashMap content to call this function to clear the entries that are not referenced externally. However, if WeakHashMap is generated in advance and the WeakHashMap has never been accessed before GC, isn't it enough to release the memory?
public class WeakHashMapTest1 { public static void main(String[] args) { List<WeakHashMap<long[][], long[][]>> maps = new ArrayList<WeakHashMap<long[][], long[][]>>(); for (int i = 0; i < 1000000; i++) { WeakHashMap<long[][], long[][]> d = new WeakHashMap<long[][], long[][]>(); d.put(new long[1000][1000], new long[1000][1000]); maps.add(d); System.gc(); System.err.println(i); } }}
This test cannot run a few cycles and the memory overflows. Sure enough, WeakHashMap didn't automatically release unnecessary memory at this time.
Public class WeakHashMapTest2 {public static void main (String [] args) throws Exception {List <WeakHashMap <long [] [], long [] []> maps = new ArrayList <WeakHashMap <long [] [], long [] []> (); for (int I = 0; I <1000; I ++) {WeakHashMap <long [] [], long [] []> d = new WeakHashMap <long [] [], long [] []> (); d. put (new long [1000] [1000], new long [1000] [1000]); maps. add (d); System. gc (); System. err. println (I); for (int j = 0; j <I; j ++) {System. err. println (j + "size" + maps. get (j ). size ());}}}}
Private static class Entry <K, V> extends WeakReference <K> implements Map. entry <K, V> Entry (K key, V value, ReferenceQueue <K> queue, int hash, Entry <K, V> next) {super (key, queue ); this. value = value; this. hash = hash; this. next = next ;}
Note that it constructs the Statement of the parent class: "super (key, queue);", which is passed in as the key, so the key is weakly referenced, value is directly strongly referenced in this. value. In System. during gc (), the byte array in the key is recycled, while the value is maintained (the value is strongly associated with the entry, the entry is associated with the map, and the map is associated with the arrayList ).
How can we prove that the byte in the key has been recycled? You can analyze the memory image exported when the memory overflows, or draw a conclusion through the following small test:
for (int i = 0; i < 10000; i++) { WeakHashMap<long[][], Object> d = new WeakHashMap<long[][], Object>(); d.put(newlong[1000][1000], new Object()); maps.add(d); System.gc(); System.err.println(i); }
The code above, even if it is executed 10000 times, proves that the long array in the key is indeed recycled. In the for loop, a new WeakHashMap is created each time. After the put operation, GC recycles the long array in the key of WeakReference and notifies the ReferenceQueue of the event, however, there is no corresponding action to trigger WeakHashMap to process ReferenceQueue. Therefore, the key encapsulated by WeakReference still exists in WeakHashMap, and its corresponding value also exists. (That is, long is recycled, but new Object is not recycled)
When is the value cleared?
The two examples show the maps in the second example. get (j ). size () triggers the collection of values. How can this be triggered. view WeakHashMap source code. We can see that the size method calls the expungeStaleEntries method. This method traverses the entry (in quene) to be recycled by the vm, sets the entry value to null, and recycles the memory. Therefore, the key is cleared during GC, and the value is cleared after the key is cleared and WeakHashMap is accessed.
Q: The quene of key is the same as the quene of map, and the poll operation will reduce a reference. The problem is that if the key is cleared first, when expungeStaleEntries traverses quene, can the entry corresponding to the recycled key still be obtained ???
For how long data in the key is recycled when System. GC is executed, see WeakReference referenceQuene.
WeakHashMap
public class WeakHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>
Hash table-Based Map implemented with weak keys. In WeakHashMap, when a key is no longer used normally, its entries are automatically removed. More precisely, for a given key, the existence of its ing does not prevent the garbage collector from discarding the key, which makes the key terminable and terminated, then it is recycled. When a key is discarded, its entries are effectively removed from the ing. Therefore, the behavior of this class is different from that of other Map implementations. Both the null value and the null key are supported. This class has similar performance characteristics as the HashMap class, and has the same initial capacity and loading factor as the performance parameter.
Like most collection classes, this class is not synchronized. You can use the Collections. synchronizedMap method to construct a synchronized WeakHashMap.
This class is mainly used with such a key object, and its equals method uses the = Operator to test the object identifier.
Once the key is discarded, it will never be created again. Therefore, it is impossible to search for the key in WeakHashMap after a period of time, so you do not have to be surprised that the key has been removed. This class is very suitable for use with key objects that are not based on object identifiers as equals methods, such as String instances.
However, the WeakHashMap entry will be automatically removed if the key is discarded for this re-creation key object, which is confusing.
The behavior of the WeakHashMap class depends partly on the action of the garbage collector. Therefore, several common (although not necessary) Map constants do not support this class.
Because the Garbage Collector may discard keys at any time, WeakHashMap is like an unknown thread that is quietly removed. In particular, even if the WeakHashMap instance is synchronized and no value assignment method is called, The size method may return a small value after a period of time. For the isEmpty method, false may be returned, then return true. For the given key, the containsKey method may return true and false. For the given key, the get method may return a value, but then return null, for keys that used to appear in the ing, the put method returns null, while the remove Method returns false. Check the key set, value set, and item set to generate fewer and fewer elements.
Each key object in WeakHashMap is indirectly stored as a weak reference indicator object. Therefore, whether in the ing or out of the ing, the key is automatically removed only after the Garbage Collector clears the weak reference of a key.
Implementation Note: Value objects in WeakHashMap are maintained by normal strong references. Therefore, be careful to ensure that the value object does not directly or indirectly strongly reference its own key, because this will prevent the key from being discarded. Note that a value object can indirectly reference its corresponding key through WeakHashMap itself; that is, a value object can strongly reference another key object, the value object associated with the key object instead strongly references the key of the first value object. One way to solve this problem is to wrap the value itself in WeakReferences before insertion, such as m. put (key, new WeakReference (value), and then unpack with get.
All the iterators returned by the "collection view method" of this class fail quickly.: After the iterator is created, if the ing is modified from the structure, unless it is modified in any way at any time through the iterator's own remove or add method, concurrentModificationException will be thrown by the iterator. Therefore, in the face of concurrent modifications, the iterator quickly fails completely, rather than risking any uncertain behavior at any time in the future. Note: The Fast failure behavior of the iterator cannot be guaranteed. In general, when there are non-synchronous concurrent modifications, it is impossible to make any firm guarantee. The quick failure iterator tries its best to throw ConcurrentModificationException. Therefore, it is incorrect to compile the program that depends on this exception.
The correct method is: the fast failure behavior of the iterator should only be used to detect bugs.
Note 1: both the null value and the null key are supported.
NOTE 2: It is not thread-safe.
Note 3: The Fast failure behavior of the iterator cannot be guaranteed.
Note 4: WeakHashMap is unordered.
Note 5: Make sure that the value object does not directly or indirectly strongly reference its own key,
This prevents key discarding. However, a value object can indirectly reference its corresponding key through WeakHashMap itself; that is, a value object can strongly reference another key object, the value object associated with the key object instead strongly references the key of the first value object, forming a loop. One way to solve this problem is to wrap the value itself in WeakReferences before insertion, such as m. put (key, new WeakReference (value), and then unpack with get.
I am the dividing line of tiantiao