Four Java reference types

Four Java reference types

  • 1. FinalReference:

Objects obj = new object() / / new are strong references
As long as the strong reference exists, the garbage collector will never recycle the referenced object. Even when the memory is insufficient, the JVM will directly throw OutOfMemoryError and will not recycle it. If you want to break the connection between the strong reference and the object, you can assign the strong reference to null, so that the JVM can reclaim the object in time

  • 2. Soft reference

Object obj= new Object()
SoftReference sr = new SoftReference<>(obj);// Obj is a soft reference
When there is enough memory, the soft reference object will not be recycled. Only when there is insufficient memory, the system will recycle the soft reference object. If there is still not enough memory after recycling the soft reference object, a memory overflow exception will be thrown. This feature is often used to implement caching technology, such as web page caching, image caching and so on.

  • 3. Weak reference

Object obj= new Object()
WeakReference wr = newWeakReference<>(obj);// Obj is a soft reference
The reference strength of weak references is weaker than that of soft references. No matter whether the memory is enough or not, as long as the JVM starts garbage collection, those objects associated with weak references will be recycled. In jdk1 After 2, use Java Lang.ref.weakreference to represent weak reference.

  • 4. Phantom reference

Object obj= new Object()
PhantomReference pr = new PhantomReference <>(obj);// Obj is a soft reference
Virtual reference is the weakest reference relationship. If an object only holds virtual reference, it may be recycled at any time as if it has no reference. In jdk1 2. After that, it is represented by the phantom reference class. By looking at the source code of this class, it is found that it has only one constructor and one get() method, and its get() method only returns a null, that is, it will never be used to obtain objects through virtual references. Virtual references must be used together with ReferenceQueue reference queue.

References and objects

Each programming language has its own way of manipulating elements in memory, for example, through pointers in C and C + +, and through "references" in Java.
In Java, everything is regarded as an object, but the identifier we operate on is actually a reference to the object.

//Create a reference, which can exist independently and does not necessarily need to be associated with an object
String s;

By pointing the identifier called "reference" to an object, you can implement the operation object through this reference.

String str = new String("abc");
System.out.println(str.toString());

   

In jdk1 Before 2, the definition in Java was very traditional: if the value stored in the data of reference type represents the starting address of another memory, it is called that this memory represents a reference.
The garbage collection mechanism in Java needs to rely on the concept of "reference" when judging whether to recycle an object.
In different garbage collection algorithms, the judgment methods of references are different:

  • Reference counting method: add a reference counter for each object. Whenever a reference points to it, the counter will increase by 1. When the reference fails, the counter will decrease by 1. When the counter is 0, it is considered that the object can be recycled (this method has been abandoned in Java at present).
  • Reachability analysis algorithm: search down from an object called GC Roots. If an object is not connected to GC Roots by any reference chain, it indicates that the object is unavailable.

JDK1.2 previously, an object had only two states of "referenced" and "not referenced", which would not describe objects in some special cases, such as objects that need to be retained when memory is sufficient and discarded when memory is tight.
Four reference types
So in JDK After 1.2, Java expanded the concept of reference and divided it into four kinds: Strong Reference, Soft Reference, Weak Reference and Phantom Reference. The strength of these four kinds of references decreased in turn.

1, Strong reference

Strong references are declared by default in Java, such as:

Object obj = new Object(); //As long as obj also points to the Object object, the Object object will not be recycled
obj = null;  //Manually set null

As long as the strong reference exists, the garbage collector will never recycle the referenced object. Even when the memory is insufficient, the JVM will directly throw OutOfMemoryError and will not recycle it. If you want to break the connection between the strong reference and the object, you can assign the strong reference to null, so that the JVM can reclaim the object in time

2, Soft reference

Soft references are used to describe some non essential but still useful objects. When there is enough memory, the soft reference object will not be recycled. Only when there is insufficient memory, the system will recycle the soft reference object. If there is still not enough memory after recycling the soft reference object, a memory overflow exception will be thrown. This feature is often used to implement caching technology, such as web page caching, image caching and so on.
In jdk1 After 2, use Java Lang.ref.softreference class to represent the soft reference.

The following is an example to further illustrate the difference between strong reference and soft reference:
Before running the following Java code, you need to configure the parameters - Xms2M -Xmx3M, set the initial memory of the JVM to 2M and the maximum available memory to 3M.

First, let's test the strong reference. On the premise of limiting the memory of the JVM, the following code runs normally

public class TestOOM {
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
     <span class="token function">testStrongReference</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">testStrongReference</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">// When new byte is 1M, the program runs normally</span>
    <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> buff <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">byte</span><span class="token punctuation">[</span><span class="token number">1024</span> <span class="token operator">*</span> <span class="token number">1024</span> <span class="token operator">*</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

But if we will

byte[] buff = new byte[1024 * 1024 * 1];

 

    Replace with creating a byte array with a size of 2M

    byte[] buff = new byte[1024 * 1024 * 2];
    
     

      If the memory is not enough, the program will directly report an error, and the strong reference will not be recycled

      Next, let's take a look at the difference between soft references. In the following example, 10 byte arrays with a size of 1M are continuously created and assigned to soft references, and then these objects are printed out through circular traversal.

      public class TestOOM {
          private static List<Object> list = new ArrayList<>();
          public static void main(String[] args) {
               testSoftReference();
          }
          private static void testSoftReference() {
              for (int i = 0; i < 10; i++) {
                  byte[] buff = new byte[1024 * 1024];
                  SoftReference<byte[]> sr = new SoftReference<>(buff);
                  list.add(sr);
              }
      
          System<span class="token punctuation">.</span><span class="token function">gc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//Actively notify garbage collection</span>
          
          <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> list<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
              Object obj <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>SoftReference<span class="token punctuation">)</span> list<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
              System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span>
          
      <span class="token punctuation">}</span>
      

      }

      Print results:


      We found that no matter how many soft reference objects are created in the loop, only the last object is retained in the print result, and all other objs are empty and recycled.
      This shows that in the case of insufficient memory, soft references will be automatically recycled.
      It is worth noting that the soft buff object has been used by the compiler after the soft buff object has been optimized. However, it is still worth noting that the soft buff object has been used by the compiler.
      If we modify the above example slightly:

       private static void testSoftReference() {
              byte[] buff = null;
      
          <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
              buff <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">byte</span><span class="token punctuation">[</span><span class="token number">1024</span> <span class="token operator">*</span> <span class="token number">1024</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
              SoftReference<span class="token operator">&lt;</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">&gt;</span> sr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SoftReference</span><span class="token operator">&lt;</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>buff<span class="token punctuation">)</span><span class="token punctuation">;</span>
              list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>sr<span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span>
      
          System<span class="token punctuation">.</span><span class="token function">gc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//Actively notify garbage collection</span>
          
          <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> list<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
              Object obj <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>SoftReference<span class="token punctuation">)</span> list<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
              System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span>
      
          System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"buff: "</span> <span class="token operator">+</span> buff<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      

      The buff cannot be garbage collected due to the existence of strong references, thus throwing an OOM error.

      If the only remaining reference of an object is a soft reference, the object is soft reachable. The garbage collector does not collect soft accessible objects as much as it collects weakly accessible objects. On the contrary, it collects soft accessible objects only when it really "needs" memory.

      3, Weak reference

      The reference strength of weak references is weaker than that of soft references. No matter whether the memory is enough or not, as long as the JVM starts garbage collection, those objects associated with weak references will be recycled. In jdk1 After 2, use Java Lang.ref.weakreference to represent weak reference.
      Let's test weak references in the same way as soft references:

         private static void testWeakReference() {
              for (int i = 0; i < 10; i++) {
                  byte[] buff = new byte[1024 * 1024];
                  WeakReference<byte[]> sr = new WeakReference<>(buff);
                  list.add(sr);
              }
      
          System<span class="token punctuation">.</span><span class="token function">gc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//Actively notify garbage collection</span>
          
          <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> list<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
              Object obj <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>WeakReference<span class="token punctuation">)</span> list<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
              System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
      

      Print results:

      It can be found that all objects associated with weak references have been garbage collected.

      4, Virtual reference

      Virtual reference is the weakest reference relationship. If an object only holds virtual reference, it may be recycled at any time as if it has no reference. In jdk1 2. After that, it is represented by the phantom reference class. By looking at the source code of this class, it is found that it has only one constructor and one get() method, and its get() method only returns a null, that is, it will never be used to obtain objects through virtual references. Virtual references must be used together with ReferenceQueue reference queue.

      public class PhantomReference<T> extends Reference<T> {
          /**
           * Returns this reference object's referent.  Because the referent of a
           * phantom reference is always inaccessible, this method always returns
           * <code>null</code>.
           *
           * @return  <code>null</code>
           */
          public T get() {
              return null;
          }
          public PhantomReference(T referent, ReferenceQueue<? super T> q) {
              super(referent, q);
          }
      }
      that
      

      How is the ReferenceQueue in its construction method used?

      5, ReferenceQueue

      The reference queue can be used together with soft reference, weak reference and virtual reference. When the garbage collector is ready to recycle an object, if it finds that it still has a reference, it will add the reference to the associated reference queue before recycling the object. The program can judge whether the referenced object will be garbage collected by judging whether a reference has been added to the reference queue, so that some necessary measures can be taken before the object is recycled.

      Unlike soft and weak references, virtual references must be used with reference queues.

      Keywords: Java

      Added by ubersmuck on Wed, 09 Feb 2022 06:13:34 +0200