There are 4 types of references in Java: StrongReference, SoftReference, WeakReference and PhantomReference (the legendary ghost reference haha),
These four types of references are closely related to GC. Let us look at their definitions and usage scenarios one by one:
1. Strong Reference
StrongReference is Java's default reference implementation. It will survive in the JVM as long as possible. When no object points to it, it will be recycled after GC execution.
Java code
Copy the code code as follows:
@Test
public void strongReference() {
Object referent = new Object();
/**
* Create StrongReference through assignment
*/
Object strongReference = referent;
assertSame(referent, strongReference);
referent = null;
System.gc();
/**
* StrongReference will not be recycled after GC
*/
assertNotNull(strongReference);
}
2. WeakReference & WeakHashMap
WeakReference, 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.
Copy the code code as follows:
@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 pointing to referent, weak reference will be automatically recycled after GC
*/
assertNull(weakRerference.get());
}
WeakHashMap uses WeakReference as key. Once there is no strong reference to the key, WeakHashMap will automatically delete the relevant entry after GC.
Copy the code code as follows:
@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 the ReferenceQueue so that they can be cleared the next time getTable is called
*/
Thread.sleep(1000);
/**
* Once there is no strong reference to the key, WeakHashMap will automatically delete the relevant entry after GC
*/
assertFalse(weakHashMap.containsValue(value));
}
3.SoftReference
SoftReference has basically the same characteristics as WeakReference. The biggest difference is that SoftReference will retain the reference as long as possible until the JVM runs out of memory before it is recycled (virtual machine guarantee). This feature makes SoftReference very suitable for caching applications.
Copy the code code as follows:
@Test
public void softReference() {
Object referent = new Object();
SoftReference<Object> softRerference = new SoftReference<Object>(referent);
assertNotNull(softRerference.get());
referent = null;
System.gc();
/**
* soft references will only be recycled before jvm OutOfMemory, so it is very suitable for caching applications
*/
assertNotNull(softRerference.get());
}
4. PhantomReference
As the protagonist of this article, Phantom Reference is very different from WeakReference and SoftReference, because its get() method always returns null, which is where its name comes from.
Java code
Copy the code code as follows:
@Test
public void phantomReferenceAlwaysNull() {
Object referent = new Object();
PhantomReference<Object> phantomReference = new PhantomReference<Object>(referent, new ReferenceQueue<Object>());
/**
* The get method of phantom reference always returns null
*/
assertNull(phantomReference.get());
}
You may ask, what is the use of a reference that always returns null? Please pay attention to the second parameter ReferenceQueue when constructing PhantomReference (in fact, WeakReference & SoftReference can also have this parameter).
The only use of PhantomReference is to track when the referent is enqueueed into the ReferenceQueue.
5. RelevanceQueue
When a WeakReference starts to return null, the object it points to is ready to be recycled. At this time, some appropriate cleanup work can be done. Pass a ReferenceQueue to the constructor of a Reference. When the object is recycled, the virtual machine will automatically The object is inserted into the ReferenceQueue. WeakHashMap uses the ReferenceQueue to clear entries whose keys no longer have strong references.
Java code
Copy the code code as follows:
@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);
}
6. PhantomReference vs WeakReference
PhantomReference has two benefits. First, it allows us to know exactly when the object is deleted from memory. This feature can be used for some special needs (such as Distributed GC, XWork and google-guice also use PhantomReference Did some cleaning work).
Secondly, it can avoid some fundamental problems caused by finalization. As mentioned above, the only function of PhantomReference is to track when the referent is enqueueed into the ReferenceQueue, but WeakReference also has corresponding functions. What is the difference between the two?
This is about the finalize method of Object. This method will be called before gc is executed. If an object overloads the finalize method and deliberately creates a strong reference to itself within the method, this will cause this round of GC to be unable to be recycled. This object may cause any GC. The final result is that there is a lot of Garbage in the JVM but OutOfMemory. This problem can be avoided by using PhantomReference, because PhantomReference is in finalize It is recycled after the method is executed, which means that it is impossible to get the original reference at this time, so the above problem will not occur. Of course, this is a very extreme example and generally does not occur.
7. Comparison
Soft vs Weak vs Phantom References | ||||
---|---|---|---|---|
Type | Purpose | Use | When GCed | Implementing Class |
Strong Reference | An ordinary reference. Keeps objects alive as long as they are referenced. | normal reference. | Any object not pointed to can be reclaimed. | default |
Soft Reference | Keeps objects alive provided there's enough memory. | to keep objects alive even after clients have removed their references (memory-sensitive caches), in case clients start asking for them again by key. | After a first gc pass, the JVM decides it still needs to reclaim more space. | java.lang.ref.SoftReference |
Weak Reference | Keeps objects alive only while they're in use (reachable) by clients. | Containers that automatically delete objects no longer in use. | After gc determines the object is only weakly reachable | java.lang.ref.WeakReference java.util.WeakHashMap |
Phantom Reference | Lets you clean up after finalization but before the space is reclaimed (replaces or augments the use offinalize()) | Special clean up processing | After finalization. | java.lang.ref.PhantomReference |
8. Summary
General applications will not involve Reference programming, but understanding this knowledge will be helpful in understanding the working principle of GC and performance tuning. It may also be used when implementing some basic facilities such as caching. I hope this article can be helpful. help.