If an object in memory has no reference, it means that the object is no longer used, and it can become a candidate for garbage collection. However, because the running time of the garbage collector is uncertain, the actual recycling time of the objects that can be garbage collected is uncertain. For an object, as long as there is a reference, it will always exist in memory. If there are more and more objects like this, exceeding the total memory in the JVM, the JVM will throw an OutOfMemory error. Although the specific operation of garbage collection is controlled by the JVM, developers can still interact with the garbage collector to a certain extent, and the purpose is to better help the garbage collector manage the application's memory. This interaction method is to use the java.lang.ref package introduced by JDK 1.2.
1 Strong Quote
Strong citations are the most common citations used. If an object has a strong reference, the garbage collector will never recycle it. When the memory space is insufficient, the Java virtual machine would rather throw an OutOfMemoryError error to cause the program to terminate abnormally, and would not recycle objects with strong references to solve the problem of insufficient memory.
For example, Date date = new Date(), date is a strong reference to an object. Strong references to objects can be passed everywhere in the program. In many cases, multiple references will point to the same object at the same time. The existence of strong references limits the survival time of an object in memory. If object A contains a strong reference to object B, then in general, object B's survival time will not be shorter than object A. If object A does not explicitly set the reference of object B to null, only after object A is garbage collected will object B no longer have a reference pointing to it, and it will be possible to get the opportunity to be garbage collected.
Example code:
package com.skywang.java;public class StrongReferenceTest { public static void main(String[] args) { MyDate date = new MyDate(); System.gc(); }} Running results:
<No output>
The result shows that even though garbage collection is explicitly called, it is a strong reference for date, and date is not recycled.
In addition to strong references, the java.lang.ref package provides different reference methods to an object. The JVM's garbage collector has different ways of handling different types of references.
2 Soft Quotations
If an object only has soft references, the memory space is sufficient and the garbage collector will not recycle it; 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. Soft references can be used to implement memory-sensitive caches.
A soft reference can be used in conjunction with a reference queue (ReferenceQueue). If the object referenced by the soft reference is recycled by the garbage collector, the Java virtual machine will add the soft reference to the associated reference queue.
Soft references are weaker than strong references in strength and are represented by SoftReference. Its function is to tell the garbage collector which objects in the program are less important and can be temporarily recycled when there is insufficient memory. When there is insufficient memory in the JVM, the garbage collector will free objects that are only pointed to by soft references. If all these objects are released and the memory is insufficient, an OutOfMemory error will be thrown. Soft references are ideal for creating caches. When the system is insufficient, the contents in the cache can be released. For example, consider an image editor program. The program will read all the contents of the image file into memory for easy processing. Users can also open multiple files at the same time. When there are too many files opened at the same time, it may cause insufficient memory. If soft references are used to point to the contents of the image file, the garbage collector can reclaim this memory when necessary.
Example code:
package com.skywang.java;import java.lang.ref.SoftReference;public class SoftReferenceTest { public static void main(String[] args) { SoftReference ref = new SoftReference(new MyDate()); ReferenceTest.drainMemory(); }} Running results:
<No output>
Results: When memory is insufficient, the soft reference is terminated. When soft references are prohibited,
SoftReference ref = new SoftReference(new MyDate());ReferenceTest.drainMemory();
Equivalent to
MyDate date = new MyDate();// It is up to the JVM to run if(JVM.Insufficient memory()) { date = null; System.gc();} 3 Weak quotes
Weak reference is weaker than soft reference in strength and is expressed by the WeakReference class. Its purpose is to refer to an object, but it does not prevent the object from being recycled. If a strong reference is used, as long as the reference exists, the referenced object cannot be recycled. Weak citations do not have this problem. When the garbage collector is running, if all references to an object are weak references, the object will be recycled. The function of weak references is to solve the coupling relationship between objects in survival time brought by strong references. The most common use of weak references is in collection classes, especially in hash tables. The hash table interface allows any Java object to be used as a key. When a key-value pair is put into the hash table, the hash table object itself has a reference to these key and value objects. If this reference is a strong reference, then as long as the hash table object itself is still alive, the key and value objects contained in it will not be recycled. If a hash table with a long survival time contains many key-value pairs, it may eventually consume all memory in the JVM.
The solution to this situation is to use weak references to reference these objects so that both key and value objects in the hash table can be garbage collected. WeakHashMap is provided in Java to meet this common need.
Sample code:
package com.skywang.java;import java.lang.ref.WeakReference;public class WeakReferenceTest { public static void main(String[] args) { WeakReference ref = new WeakReference(new MyDate()); System.gc(); }} Running results:
obj [Date: 1372142034360] is gc
Results: When JVM garbage collection runs, weak references are terminated.
WeakReference ref = new WeakReference(new MyDate());System.gc();
Equivalent to:
MyDate date = new MyDate();// Garbage collection if(JVM.Insufficient memory()) { date = null; System.gc();} The difference between weak references and soft references is that objects with only weak references have a shorter life cycle. During the process of a garbage collector thread scanning the memory area under its jurisdiction, once an object with only weak references is found, its memory will be recycled regardless of whether the current memory space is sufficient or not. However, since the garbage collector is a thread with very low priority, it may not necessarily be discovered very quickly for objects that only have weak references.
A weak reference can be used in conjunction with a reference queue (ReferenceQueue). If the object referenced by a weak reference is garbage collected, the Java virtual machine will add the weak reference to the associated reference queue.
4 illusion quotes
Also known as ghost quotes~ Before introducing ghost quotes, we must first introduce the object termination mechanism provided by Java. There is a finalize method in the Object class. The original intention of its design is to perform some cleaning work before an object is actually recycled. Because Java does not provide a mechanism similar to C++ destructor, it is implemented through the finalize method. But the problem is that the run time of the garbage collector is not fixed, so the actual running time of these cleaning work cannot be predicted. A phantom reference can solve this problem. When creating a ghost reference PhantomReference, you must specify a reference queue. When the finalize method of an object has been called, the ghost reference of the object will be added to the queue. By checking the contents in the queue, you will know whether an object is ready to be recycled.
The use of ghost references and their queues is rare, and is mainly used to implement relatively fine memory usage control, which is very meaningful for mobile devices. The program can request memory to create a new object after determining that an object is to be recycled. In this way, the memory consumed by the program can be maintained at a relatively low amount.
For example, the following code gives an example of the implementation of a buffer.
public class PhantomBuffer { private byte[] data = new byte[0]; private ReferenceQueue<byte[]> queue = new ReferenceQueue<byte[]>(); private PhantomReference<byte[]> ref = new PhantomReference<byte[]>(data, queue); public byte[] get(int size) { if (size <= 0) { throw new IllegalArgumentException("Wrong buffer size"); } if (data.length < size) { data = null; System.gc(); //Force run the garbage collector try { queue.remove(); //This method will block until the queue is non-empty ref.clear(); //The ghost reference will not be automatically cleared, you must run ref = null; data = new byte[size]; ref = new PhantomReference<byte[]>(data, queue); } catch (InterruptedException e) { e.printStackTrace(); } } return data; }} In the above code, every time a new buffer is applied, it is first ensured that the byte array of the previous buffer has been successfully recycled. The remove method that references the queue will block until a new ghost reference is added to the queue. However, it should be noted that this approach will cause the garbage collector to be run too many times, which may cause the program to be too low throughput.
Sample code:
package com.skywang.java;import java.lang.ref.ReferenceQueue;import java.lang.ref.PhantomReference;public class PhantomReferenceTest { public static void main(String[] args) { ReferenceQueue queue = new ReferenceQueue(); PhantomReference ref = new PhantomReference(new MyDate(), queue); System.gc(); }} Running results:
obj [Date: 1372142282558] is gc
The result shows that the illusion reference is terminated after instantiation.
ReferenceQueue queue = new ReferenceQueue();PhantomReference ref = new PhantomReference(new MyDate(), queue);System.gc();
Equivalent to:
MyDate date = new MyDate();date = null;