Detailed explanation and comparison of four kinds of references in Java

catalogue

1 four references

There are four types of references in Java: StrongReference, SoftReference, WeakReference and phantom reference,
These four types of references are closely related to GC. Let's look at their definitions and usage scenarios one by one

1.1 strong reference

Strong reference is the default reference implementation of Java and is the most commonly used reference. If an object has a strong reference, it is similar to an essential commodity. The garbage collector will never recycle it. It will survive in the JVM as long as possible.
When the memory space is insufficient, the Java virtual machine would rather throw OutOfMemoryError error to make the program terminate abnormally, rather than solve the problem of insufficient memory by arbitrarily recycling objects with strong references
When no object points to it, it will be recycled after GC execution
Code example:

@Test  
public void strongReference() {  
    Object referent = new Object();        
    /** 
     * Create StrongReference by assignment  
     */  
    Object strongReference = referent;  
      
    assertSame(referent, strongReference);   
    referent = null;  
    System.gc();  
      
    /** 
     * StrongReference Not recycled after GC 
     */  
    assertNotNull(strongReference);  
}  

1.2 soft reference

SoftReference will keep the reference as long as possible and will not be recycled until the JVM is out of memory (virtual machine guarantee). This feature makes SoftReference very suitable for caching applications
If an object has only soft references, it is similar to a commodity that can have things. If the memory is insufficient, the garbage collector will not recycle the memory. As long as the garbage collector does not recycle it, the object can be used by the program. Soft references can be used to implement memory sensitive caching.
The soft reference can be used in conjunction with a reference queue. If the object referenced by the soft reference is garbage collected, the Java virtual machine will add the soft reference to the reference queue associated with it

@Test  
public void softReference() {  
    Object referent = new Object();  
    SoftReference<Object> softRerference = new SoftReference<Object>(referent);  
  
    assertNotNull(softRerference.get());  
      
    referent = null;  
    System.gc();  
      
    /** 
     *  soft references It can only be recycled before jvm OutOfMemory, so it is very suitable for caching applications 
     */  
    assertNotNull(softRerference.get());  
}  

1.3 weak reference

Weak reference, as the name suggests, is a weak reference. When the referenced object no longer has a strong reference in the JVM, the weak reference will be automatically recycled after GC. If an object has only weak references, it is similar to a commodity that can have things.

The difference between weak references and soft references is that objects with only weak references have a shorter life cycle. When the garbage collector thread scans the memory area under its jurisdiction, once it finds an object with only weak references, it will reclaim its memory regardless of whether the current memory space is sufficient or not. However, since the garbage collector is a low priority thread, it is not necessary to quickly find objects with only weak references.
A weak reference can be used in conjunction with a reference queue. If the object referenced by the weak reference is garbage collected, the Java virtual machine will add the weak reference to the associated reference queue.

@Test  
public void weakReference() {  
    Object referent = new Object();  
    WeakReference<Object> weakRerference = new WeakReference<Object>(referent);  
    assertSame(referent, weakRerference.get());  
    referent = null;  
    System.gc();        
    /** 
     * Once there is no strong reference to the referent, the weak reference will be automatically recycled after GC 
     */  
    assertNull(weakRerfere

Appendix: WeakHashMap
The WeakHashMap uses the WeakReference as the key. Once there is no strong reference to the key, the WeakHashMap will automatically delete the relevant entry after GC

@Test  
public void weakHashMap() throws InterruptedException {  
    Map<Object, Object> weakHashMap = new WeakHashMap<Object, Object>();  
    Object key = new Object();  
    Object value = new Object();  
    weakHashMap.put(key, value);  
    assertTrue(weakHashMap.containsValue(value));  
      
    key = null;  
    System.gc();    
    /** 
     * Wait for invalid entries to enter ReferenceQueue so that they can be cleaned up the next time getTable is called 
     */  
    Thread.sleep(1000);  
      
    /** 
     * Once there is no strong reference to the key, the WeakHashMap will automatically delete the relevant entry after GC 
     */  
    assertFalse(weakHashMap.containsValue(value));  
}  

1.4 phantom reference

Phantom reference is very different from WeakReference and SoftReference because its get() method always returns null, which is the origin of its name. Unlike other references, virtual reference does not determine the life cycle of an object. If an object holds only virtual references, it can be garbage collected at any time as if it had no references.
Virtual reference function: used to track the activity of objects being garbage collected.
One difference between virtual references and soft and weak references is that virtual references must be used in conjunction with reference queues.
When the garbage collector prepares to recycle an object, if it finds that it still has a virtual reference, it will add the virtual reference to the associated reference queue before recycling the memory of the object. 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 the necessary actions before the memory of the referenced object is recycled.

@Test  
public void phantomReferenceAlwaysNull() {  
    Object referent = new Object();  
    PhantomReference<Object> phantomReference = new PhantomReference<Object>(referent, new ReferenceQueue<Object>());  
      
    /** 
     * phantom reference The get method of always returns null  
     */  
    assertNull(phantomReference.get());  
} 

For the purpose of a reference that always returns null, please pay attention to the second parameter ReferenceQueue when constructing phantom reference (in fact, WeakReference & softreference can also have this parameter),
The only use of phantom reference is to track when a referent is enqueue d into ReferenceQueue

1.5 reference queue

When a WeakReference starts to return null, the object it points to is ready to be recycled. At this time, you can do some proper cleaning Pass a ReferenceQueue to the constructor of a Reference. When the object is recycled, the virtual opportunity will automatically insert the object into the ReferenceQueue. WeakHashMap uses the ReferenceQueue to clear the entries where the key has no strong Reference

@Test  
public void referenceQueue() throws InterruptedException {  
    Object referent = new Object();       
    ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();  
    WeakReference<Object> weakReference = new WeakReference<Object>(referent, referenceQueue);  
      
    assertFalse(weakReference.isEnqueued());  
    Reference<? extends Object> polled = referenceQueue.poll();  
    assertNull(polled);  
      
    referent = null;  
    System.gc();  
  
    assertTrue(weakReference.isEnqueued());  
    Reference<? extends Object> removed = referenceQueue.remove();  
    assertNotNull(removed);  
} 

2. Comparison of differences

2.1 virtual reference VS weak reference

PhantomReference vs WeakReference
Phantom reference has two benefits:

  • It allows us to know exactly when objects are deleted from memory. This feature can be used for some special needs (for example, phantom reference is also used in Distributed GC, XWork and Google Guice)
  • It can avoid some fundamental problems caused by finalization. The sole function of phantom reference mentioned above is to track when reference is enqueue d into ReferenceQueue, but WeakReference also has corresponding functions. What is the difference between the two?

This is about the finalize method of Object, which will be called before GC execution. If an Object overloads the finalize method and deliberately creates its own strong reference in the method, it will cause this round of GC to fail to recycle the Object and may cause any GC. The last result is that there are many Garbage but OutOfMemory in the JVM. This problem can be avoided by using phantom reference, Because PhantomReference is recycled after the finalize method is executed, it means that it is impossible to get the original reference at this time, so the above problems will not occur. Of course, this is a very extreme example, which generally does not occur

General applications will not involve Reference programming, but understanding these knowledge will be helpful to understand the working principle and performance tuning of GC, and may also be used in the implementation of some infrastructure such as caching. I hope this article can be helpful

Posted by samafua on Tue, 03 May 2022 17:20:08 +0300