We mentioned GC before, but when more and more objects are referenced in Java, there will be insufficient memory space, resulting in the error OutOfMemoryError and application termination. So why can't GC collect more objects at this time? This is related to the reference types mentioned today.
<!-- more -->
First of all, starting from JDK 1.2, the object reference is divided into four levels, so that the program can control the object life cycle more flexibly. The four levels from high to low are: strong reference, soft reference, weak reference and virtual reference.
Strong citation
Strong reference is the most commonly used reference. If an object has a strong reference, it will never be GC. For example:
Object strongReference = new Object();
When the memory space is insufficient, the JVM would rather throw OutOfMemoryError to terminate the program abnormally, rather than recycle the objects with strong references at will to solve the problem of memory shortage.
If a strong reference object is not used, it needs to be weakened so that it can be used by GC, such as the clear() method in ArrayList:
/** * Removes all of the elements from this list. The list will * be empty after this call returns. */ public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; }
If the strongly referenced object is explicitly set to null or beyond the object's life cycle, the garbage collector will recycle the object if it considers that there is no reference to the object. When to collect depends on the garbage collector.
Soft reference
If an object only has a soft reference, the garbage collector will not recycle it when the memory space is sufficient; if the memory space is insufficient, the memory of these objects will be recycled. As long as the garbage collector does not recycle it, the object can be used by the program. Let's take a look at an example:
String str = new String("abc"); SoftReference<String> softReference = new SoftReference<>(str); String result = softReference.get();
Let's take a look at get():
public T get() { T o = super.get(); // timestamp represents the last time the last soft reference was used (initialization, get()) // clock represents the time of the last GC if (o != null && this.timestamp != clock) this.timestamp = clock; return o; }
Therefore, when the soft reference is garbage collected, it also follows the LRU rule, preferentially recycling the least recently used objects for recycling.
Most of the usage scenarios of soft reference are memory sensitive cache. Specifically, we want to store the data in the cache so that it can be read quickly. However, when there is not enough memory in the JVM, we do not want the cache data to occupy the memory of the JVM. For example, with ReferenceQueue, if the object referenced by the soft reference is garbage collected, the JVM will add the soft reference to the reference queue associated with it:
ReferenceQueue<String> referenceQueue = new ReferenceQueue<>(); String str = new String("abc"); SoftReference<String> softReference = new SoftReference<>(str, referenceQueue); str = null; // Notify GC System.gc(); System.out.println(softReference.get()); // abc Reference<? extends String> reference = referenceQueue.poll(); System.out.println(reference); //null
However, it should be noted that the use of soft reference caching may lead to the increase of Full GC.
Weak reference
If an object has only a weak reference, its life cycle is shorter than that of a soft reference. When the garbage collector thread scans the memory area under its jurisdiction, once it finds an object with only weak references, it will be recycled whether the current memory space is enough or not. However, because the garbage collector is a low priority thread, it is not necessarily easy to find objects with only weak references. Its use is:
String str = new String("abc"); WeakReference<String> weakReference = new WeakReference<>(str); str = weakReference.get();
When it comes to weak references, we have to mention WeakHashMap. Compared with HashMap, when the memory allocated to the JVM is insufficient, HashMap would rather throw an OutOfMemoryError exception than recycle its corresponding unreferenced objects, while WeakHashMap will recycle the objects stored in it but referenced.
WeakHashMap tells the GC to recycle the stored values by assigning null to the values of some unreferenced keys. If we specially pass in a key with null key, WeakHashMap will set the key to a special object. The source code is:
public V put(K key, V value) { // key will be reassigned Object k = maskNull(key); int h = hash(k); Entry<K,V>[] tab = getTable(); int i = indexFor(h, tab.length); for (Entry<K,V> e = tab[i]; e != null; e = e.next) { if (h == e.hash && eq(k, e.get())) { V oldValue = e.value; if (value != oldValue) e.value = value; return oldValue; } } modCount++; Entry<K,V> e = tab[i]; tab[i] = new Entry<>(k, value, queue, h, e); if (++size >= threshold) resize(tab.length * 2); return null; } /** * Value representing null keys inside tables. * Special key */ private static final Object NULL_KEY = new Object(); /** * Use NULL_KEY for key if it is null. */ private static Object maskNull(Object key) { return (key == null) ? NULL_KEY : key; }
Virtual reference
As the name implies, a phantom reference is a virtual thing. Unlike several other references, a virtual reference does not determine the life cycle of an object. If an object holds only virtual references, it can be recycled by the garbage collector at any time, just as it does not have any references.
Virtual references are mainly used to track the activities of objects recycled by the garbage collector. The difference between virtual reference and soft reference and weak reference is as follows:
A virtual reference must be used in conjunction with a reference queue. When the garbage collector is ready to recycle an object, if it finds that it has a virtual reference, it will add the virtual reference to the reference queue associated with the object before reclaiming its memory.
For example:
String str = new String("abc"); ReferenceQueue queue = new ReferenceQueue(); // Creating a virtual reference requires that it must be associated with a reference queue PhantomReference pr = new PhantomReference(str, queue);
The program can know whether the referenced object will be garbage collected by judging whether the virtual reference has been added to the reference queue. If the program finds that a virtual reference has been added to the reference queue, it can take necessary actions before the memory of the referenced object is recycled, which can also be understood as a callback method.
summary
The level and stren gt h of the four references in Java are: strong reference, soft reference, weak reference, virtual reference.
Through the table, explain its characteristics:
reference type | Garbage collection time | Usage scenarios | survival time |
---|---|---|---|
Strong citation | Never | General state of the object | When the JVM stops running |
Soft reference | When out of memory | Object cache | When out of memory |
Weak reference | Normal garbage collection | Object cache | End after garbage collection |
Virtual reference | Normal garbage collection | Garbage collection of tracking objects | End after garbage collection |
If you are interested, you can visit my blog or pay attention to my public number and headline number. Maybe there will be unexpected surprises.