Java–》4 kinds of references: strong and weak

Recommended links:
Summary–》[Java]
Summary–》[Mysql]
Summary–》【Redis】
Summary–》[Kafka]
Summary–》[Spring]
Summary–》[SpringBoot]
Summary–》[MyBatis, MyBatis-Plus]
Summary–》[Linux]
Summary–》[MongoDB]
Summary–》[Elasticsearch]

Java–》4 kinds of references: strong and weak

  • 1. NormalReference = Strong = Normal = Default
  • 2. SoftReference = soft
  • 3. WeakReference = weak
  • 4. PhantomReference = virtual
  • 5. The difference between the four types of citations
    • 1. Writing method
    • 2. Recycling mechanism
    • 3. Usage scenarios

Quoted definition:
1. Our data type must be a reference type
2. The data stored in our type of data must be the starting address of another memory.

image.png

1. NormalReference = Strong = Normal = Default

Strong references are the most commonly used references. Strong references will not be recycled when the program is out of memory (OOM).

import java.io.IOException;

public class T01_NormalReference {<!-- -->
    public static void main(String[] args) throws IOException {<!-- -->
        // Strong reference = ordinary reference = default reference. As long as there is a reference pointing to this object, the GC will not recycle it.
        M m = new M();
        // Set m to null, and there will no longer be a reference to the object M. In other words, the reference between m and new M() will be interrupted, and there will no longer be a connection. Run the program again at this time, You will find that the M object was recycled by GC
        //m = null;
        System.gc(); //DisableExplicitGC, display calling GC
        // The current thread must be blocked at the end, because GC is running on other threads. If the main thread exits directly, then GC will be meaningless.
        // Blocking the current thread means that the entire current program will not stop.
        System.in.read();
    }

    static class M {<!-- -->
        @Override
        // During GC, finalize() will be called
        // Finalize() is rewritten here just to observe when it is GCed, so this method never needs to be rewritten, and it should not be rewritten.
        protected void finalize() throws Throwable {<!-- -->
            System.out.println("finalize");
        }
    }
}

2. SoftReference = soft

Soft references will be recycled when the program runs out of memory.

/**
 * Soft reference
 * Soft references are used to describe some objects that are useful but not necessary.
 * For objects associated with soft references, these objects will be included in the recycling scope for the second recycling before a memory overflow exception occurs in the system.
 * If there is not enough memory for this recycling, a memory overflow exception will be thrown.
 *
 * When there is an object pointed to by a soft reference, the GC will only recycle it when the system memory is not enough. If the memory is enough, the GC will not recycle it.
 *
 * Soft references are very suitable for caching
 *
 * Note: Before running the program, set the maximum heap memory to 20M
 * Parameters: -Xms20M -Xmx20M
 */
import java.lang.ref.SoftReference;

public class T02_SoftReference {<!-- -->
    public static void main(String[] args) {<!-- -->
        // Allocate 10M byte array
        // There is an m in the stack, pointing to the soft reference SoftReference in the heap, which in turn points to the 10M byte array
        SoftReference<byte[]> m = new SoftReference<>(new byte[1024*1024*10]);
        // m.get(), get the byte array and print the hashcode value
        System.out.println(m.get()); // Print result: [B@2344fc66
        System.gc();
        try {<!-- -->
            Thread.sleep(500);
        } catch (InterruptedException e) {<!-- -->
            e.printStackTrace();
        }

        // If recycled, m.get() = null
        // If not recycled, m.get() = hashcode value of byte array
        System.out.println(m.get());//The print result is: [B@2344fc66. Although GC is called, the object is not recycled because the heap memory is enough.

        //Allocate another array of 15M. The heap will not be able to hold it. At this time, the system will garbage collect. It will be recycled once. If it is not enough, the soft references will be removed.
        byte[] b = new byte[1024*1024*15];
        // If recycled, m.get() = null
        // If not recycled, m.get() = hashcode value of byte array
        System.out.println(m.get());//Print result: null, because the heap space is not enough, the GC recycled the soft reference

    }
}

3. WeakReference = weak

A weak reference means that as long as the JVM garbage collector finds it, it will be recycled.

/**
 * Weak references will be recycled if they are subject to gc
 * If there is a strong reference pointing to the weak reference, as long as the strong reference disappears, the weak reference should be recycled. It is generally used in containers. The most typical one is ThreadLocal.

 * ThreadLocal<M> tl = new ThreadLocal<>();
 * tl.set(new M());
 *
 * 1. Where can we see that the Entry key is a weak reference?
 * Set an Entry to the threadLocals variable of the current thread. The key is the ThreadLocal object and the value is the M object.
 * Since the parent class of Entry is WeakReference, which contains ThreadLocal objects, super(key) is called, which is equivalent to new WeakReference(key).
 * So key is the ThreadLocal object pointed to by a weak reference
 *
 * 2. Why does Entry use weak references?
 * The current thread is our main thread, tl is a strong reference pointing to the ThreadLocal object, tl is a local variable, and it disappears when the method ends.
 * If the ThreadLocal object is still pointed to by a strongly referenced key, the ThreadLocal object cannot be recycled.
 * And because many threads exist for a long time, this Map will exist for a long time, and the ThreadLocal object will never be destroyed, and memory leaks may occur.
 *
 * But if the key is a weak reference, there will be no memory leak problem. As long as the strong reference disappears, the weak reference will be recycled.
 *
 * 3. Why does ThreadLocal cause memory leaks?
 * tl is a strong reference pointing to the ThreadLocal object, tl is a local variable, and it disappears when the method ends.
 * Since the key points to the ThreadLocal object through a weak reference, the point of the key is also recycled at this time, and the key becomes null.
 * Since the Map of threadLocals always exists, but the key becomes null, the value will never be accessible.
 * If this Map accumulates more and more, it will still leak memory, so the objects in ThreadLocal are no longer needed and must be removed, otherwise there will still be memory leaks.
 */

import java.lang.ref.WeakReference;

public class T03_WeakReference {<!-- -->
    public static void main(String[] args) {<!-- -->

        WeakReference<M> m = new WeakReference<>(new M());
        //Print result: com.mashibing.juc.c_022_RefTypeAndThreadLocal.T03_WeakReference$M@458ad742
        System.out.println(m.get());
        System.gc();
        //Print result: null, because weak references will definitely be recycled by GC
        System.out.println(m.get());

        // tl is the ThreadLocal object pointed to by a strong reference
        ThreadLocal<M> tl = new ThreadLocal<>();
        // key is the ThreadLocal object pointed to by a weak reference
        tl.set(new M());
        // Be sure to remove, otherwise memory leaks will occur
        tl.remove();
    }
    static class M {<!-- -->
        @Override
        // During GC, finalize() will be called
        // Finalize() is rewritten here just to observe when it is GCed, so this method never needs to be rewritten, and it should not be rewritten.
        protected void finalize() throws Throwable {<!-- -->
            System.out.println("finalize");
        }
    }
}


4. PhantomReference = virtual

The recycling mechanism of virtual references is similar to that of weak references, but before it is recycled, it will be put into the ReferenceQueue. Note that other references are passed into the ReferenceQueue after they are recycled by the JVM. Due to this mechanism, virtual references are mostly used for processing before reference destruction. Also, when a virtual reference is created, it must have a ReferenceQueue

/**
 *
 *
 * Whether an object has a virtual reference will not affect its survival time at all.
 * It is also impossible to obtain an instance of an object through a virtual reference.
 * The only purpose of setting a virtual reference association for an object is to receive a system notification when the object is recycled by the collector.
 * Neither virtual references nor weak references will affect the recycling of associated objects. If only virtual references or weak references are associated with the object,
 * Then this object will be recycled. The difference between them is that the get method of weak reference and the get method of virtual reference always return null.
 * Weak references can use ReferenceQueue, and virtual references must be used in conjunction with ReferenceQueue.
 *
 * Direct memory recycling in jdk uses virtual references. Since the scope of jvm automatic memory management is heap memory,
 * Direct memory is outside the heap memory (actually a memory mapped file, please understand the related concepts of virtual memory space by yourself),
 * Therefore, the allocation and recycling of direct memory are operated by the Unsafe class. After java applies for a piece of direct memory,
 * An object will be allocated in the heap memory to save the reference to the off-heap memory.
 * This object is managed by the garbage collector. Once this object is recycled,
 * The corresponding user thread will receive the notification and clean up the direct memory.
 *
 * In fact, a very important use of virtual references is to release off-heap memory.
 * DirectByteBuffer realizes the release of off-heap memory through virtual references.
 *
 */
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.LinkedList;
import java.util.List;

public class T04_PhantomReference {<!-- -->
    private static final List<Object> LIST = new LinkedList<>();
    private static final ReferenceQueue<M> QUEUE = new ReferenceQueue<>();



    public static void main(String[] args) {<!-- -->


        PhantomReference<M> phantomReference = new PhantomReference<>(new M(), QUEUE);


        new Thread(() -> {<!-- -->
            while (true) {<!-- -->
                LIST.add(new byte[1024 * 1024]);
                try {<!-- -->
                    Thread.sleep(1000);
                } catch (InterruptedException e) {<!-- -->
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
                // Printed result: null, virtual reference cannot get the value, but weak reference can get the value
                System.out.println(phantomReference.get());
            }
        }).start();

        new Thread(() -> {<!-- -->
            while (true) {<!-- -->
                Reference<? extends M> poll = QUEUE.poll();
                if (poll != null) {<!-- -->
                    System.out.println("--- The virtual reference object was recycled by jvm ---- " + poll);
                }
            }
        }).start();

        try {<!-- -->
            Thread.sleep(500);
        } catch (InterruptedException e) {<!-- -->
            e.printStackTrace();
        }

    }
}

5. The difference between the four types of references

1. Writing

Quotation Writing
Strong M m = new M();
Soft SoftReference m = new SoftReference<>(new byte[1024102410]);
Weak WeakReference m = new WeakReference<>(new M());
Virtual Method 1:
private static final ReferenceQueue QUEUE = new ReferenceQueue<>();
PhantomReference phantomReference = new PhantomReference<>(new M(), QUEUE);
Method two:
PhantomReference prf = new PhantomReference(new M(),new ReferenceQueue<>());

2. Recycling mechanism

Reference Recycling mechanism
Strong As long as there is a reference pointing to this object, the GC will definitely not recycle it
Soft Only when the system memory is not enough, the GC will recycle this object. If the memory is enough, the GC will not recycle it.
Weak As long as GC is used, it will be recycled
Virtual As long as GC is used, it will be recycled. This virtual reference will be loaded into the queue, and then a notification will be received. Generally, it will monitor the GC recycling phase, or recycling Used when using off-heap memory.

3. Usage scenarios

td>

Quote Usage scenario
Strong Most commonly used
Soft When creating a cache, the created objects are put into the cache. When the memory is insufficient, the JVM will recycle the previously created objects.
Weak The key in java.util.WeakHashMap in the Java source code uses weak references. Once I don’t need For a certain reference, the JVM will automatically handle it for me, so I don’t need to do other operations. Can solve the problem of memory leak.
Virtual It is used for processing before reference destruction, such as resource release or recycling of off-heap memory. Although Object.finalize() can also perform such actions, this method is both unsafe and inefficient.