In-depth understanding of the four major references of Java

Java has four types of reference: strong reference, soft reference, weak reference, virtual reference

Four major reference design functions

​ Because Java's memory allocation and memory recovery are all taken care of by the JVM. Whether an object can be recycled mainly depends on whether there is a reference to this object, which can be analyzed for reachability. Since our programmers generally do not actively call the GC method, if we want to manage the life cycle of an object, we must flexibly apply various references to create the object.

  • aim of design:

    • Allows programmers to determine the life cycle of an object through code
    • Use garbage collection

Strong citation

The most widely used, but also the most common.

Object o = new Object();

As long as an object has a strong reference associated with it, the object will never be recycled. Even if the memory is insufficient, the JVM will only throw OOM and not recycle it.

But if you want the JVM to reclaim the object, you need to break the association between the strong reference and the object.

  • Disconnect
n=null;

In order to verify, here we manually call the GC to see if the association between the strong reference and the object is interrupted, and the resource will not be reclaimed.

public class Student {
    @Override
    protected void finalize()throws Throwable{
        System.out.println(" Student 被回收了");
    }

    public static void main(String[] args) {
        Student student = new Student();
        System.gc();
        System.out.println("===============");
        student = null;
        System.gc();
    }
}
  • result:

Student was recycled

  • note

    • Do not rewrite the finalize method during development
    • Some objects can be manually assigned to NULL during development, which can remind the JVM to garbage collect these resources

Soft reference

  • Create a soft reference
SoftReference<Student> studentSoftReference = new SoftReference<Student>(new Student());
  • Soft reference is to wrap the object with SoftReference. When we need to get the wrapped object from the soft reference object, we just need to get it.
SoftReference<Student> studentSoftReference = new SoftReference<Student>(new Student());
        Student student = studentSoftReference.get();
        System.out.println(student);
  • Features:

    • When the memory is insufficient, the JVM GC will be triggered. If the memory is still insufficient after the GC, the objects in the soft reference package will be recycled.
    • That is to say, only when the memory is insufficient, the JVM will reclaim the object
  • verification:

 SoftReference<byte[]> softReference = new SoftReference<byte[]>(new byte[1024*1024*10]);
        System.out.println(softReference.get());
        System.gc();
        System.out.println(softReference.get());

        byte[] bytes = new byte[1024*1024*10];
        System.out.println(softReference.get());
  • JVM parameters need to be added when running: -Xmx20M represents the largest heap memory of 20M
  • result

[B@452b3a41

[B@452b3a41

null

  • When we manually GC, the objects in the soft-referenced object package are still okay. When we create a 10M byte, the maximum heap memory is not enough, and the soft-referenced objects are garbage collected.
  • Function: It can be used as a cache. When the memory is enough, the cache can be obtained normally. When the memory is not enough, the cache will be killed first, so that OOM will not appear.
import java.lang.ref.SoftReference;
import java.util.HashMap;

/**
 * SoftRefenceCache
 * @param <K> key的类型.
 * @param <V> value的类型.
 */
public class SoftReferenceCache<K, V> {
    private final HashMap<K, SoftReference<V>> mCache;

    public SoftReferenceCache() {
        mCache = new HashMap<K, SoftReference<V>>();
    }

    /**
     * 将对象放进缓存中,这个对象可以在GC发生时被回收
     *
     * @param key key的值.
     * @param value value的值型.
     */

    public void put(K key, V value) {
        mCache.put(key, new SoftReference<V>(value));
    }

    /**
     * 从缓存中获取value
     *
     * @param key
     *
     * @return 如果找到的话返回value,如果被回收或者压根儿没有就返* 回null
     */

    public V get(K key) {
        V value = null;

        SoftReference<V> reference = mCache.get(key);

        if (reference != null) {
            value = reference.get();
        }

        return value;
    }

    public static void main(String[] args) {
        SoftReferenceCache<Integer, String> mPersonCache = new SoftReferenceCache<Integer, String>();

        mPersonCache.put(0, ("zhong"));
        mPersonCache.put(1, ("hu"));
       

        // 去拿zhong
        String p = (String) mPersonCache.get(1);
    }
}

Weak reference

Weak reference is similar to soft reference, but the keyword is replaced with WeakReferce

 WeakReference weakReference = new WeakReference<byte[]>(new byte[1024*1024*10]);
        System.out.println(weakReference.get());
  • Features: Regardless of whether the memory is enough, it will be recycled as long as GC occurs (this is also the most obvious difference between soft references)
  • 用途:ThreadLocal、WeakHashMap。

Phantom reference

Phantom reference

 ReferenceQueue queue = new ReferenceQueue();
        PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1],queue);
        System.out.println(reference.get());
  • There is still a big difference between the use of phantom references and others.
  • result:

null

  • Because its get method directly returns null
  • To create a virtual reference object, we not only pass in the wrapped object, but also pass a ReferenceQueue (queue)
  • The virtual reference must be used together with the ReferenceQueue. When the GC prepares to reclaim an object, if it finds that it still has a phantom reference, it will add the phantom reference to the ReferenceQueue associated with it before the collection.
 ReferenceQueue queue = new ReferenceQueue();
        List<byte[]> bytes = new ArrayList<>();
        PhantomReference<Student> reference = new PhantomReference<Student>(new Student(),queue);
        new Thread(() -> {
            for (int i = 0; i < 100;i++ ) {
                bytes.add(new byte[1024 * 1024]);
            }
        }).start();

        new Thread(() -> {
            while (true) {
                Reference poll = queue.poll();
                if (poll != null) {
                    System.out.println("虚引用被回收了:" + poll);
                }
            }
        }).start();
        Scanner scanner = new Scanner(System.in);
        scanner.hasNext();
  • result

Phantom references have been recycled: java.lang.ref.PhantomReference @5ac42552

The first thread puts data in the collection, as the data becomes more and more, it must send GC

The second thread has an infinite loop, and takes data from the queue. If the data taken out is not null, then print it out

When GC occurs, the phantom reference will be recycled, and the recycled comrades will be placed in the ReferenceQueue

In NIO, virtual references can be used to manage off-heap memory

At last

  • If you feel that you are rewarded after reading it, I hope to give me a thumbs up. This will be the biggest motivation for me to update. Thank you for your support.
  • Welcome everyone to pay attention to my public account [Java Fox], focusing on the basic knowledge of java and computer, I promise to let you get something after reading it, if you don’t believe me, hit me
  • If you have different opinions or suggestions after reading, please comment and share with us. Thank you for your support and love.

image

Guess you like

Origin blog.csdn.net/issunmingzhi/article/details/110819911