[case demonstration] strong reference, soft reference, weak reference and virtual reference of JVM

1. background

To understand when objects are recycled, we need to understand the concept of object reference, so we have the following

2. Reference object structure chart in Java

3. Introduction

3.1. What is strong quotation

a. When there is not enough memory, the JVM starts to garbage collect. For a strongly referenced object, even if there is a 00M, it will not recycle the object, even if it is dead.

b. Strong reference is our most common common common object reference. As long as there is a strong reference to an object, it can indicate that the object is still "alive", and the garbage collector will not touch such an object.

In Java, the most common is strong reference. Assign an object to a reference variable, which is a strong reference.

When an object is referenced by a strong reference variable, it is in the reachable state, and it cannot be recycled by the garbage collection mechanism, even if the object will never be used in the JVM in the future.

So strong reference is one of the main reasons for Java memory leak

c. For an ordinary object, if there is no other reference relationship, as long as it exceeds the scope of the reference or explicitly assigns the corresponding (strong) reference to null, it is generally considered that it can be garbage collected (of course, the specific collection time depends on the garbage collection strategy).

Case:

package com.wfd360.demo03GC.referDemo;

/**
 * @author Pose emperor blog Garden
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 12:12
 * @description
 */
public class StrongRefer {
    /**
     * Understanding of strong quotation
     *
     * @param args
     */
    public static void main(String[] args) {
        Object obj1 = new Object();
        // Build strong references
        Object obj2 = obj1;
        // observation obj1 and obj2 Various memory addresses for
        System.out.println("obj1=" + obj1);
        System.out.println("obj2=" + obj2);
        // obj1 Create conditions that can be recycled
        obj1 = null;
        // gc recovery
        System.gc();
        // Observe the situation of each object
        System.out.println("obj1=" + obj1);
        System.out.println("obj2=" + obj2);
    }
}

From the course of test results, it can be seen that the actual object of obj 1 is not recycled;

3.2. What is soft reference

a. Soft references are used to describe some useful but not necessary objects, which need to be java.lang.ref.SoftReference class.

b. For the objects associated with soft references, they will be listed in the recycle scope for a second recycle before the system will have a memory overflow exception. If there is not enough memory in this recycle, a memory overflow exception will be thrown. After JDK 1.2, the Soft Reference class is provided to implement the Soft Reference.

c. Soft references are usually used in memory sensitive programs. For example, the cache is useful for soft references. When the memory is enough, it is reserved and recycled!

Case:

package com.wfd360.demo03GC.referDemo;

import java.lang.ref.SoftReference;

/**
 * @author Pose emperor blog Garden
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 12:12
 * @description
 */
public class SoftRefer {

    /**
     * Understanding of soft quotation
     * By setting jvm parameters, observe under different conditions
     *
     * @param -Xms5m -Xmx5m -XX:+PrintGCDetails
     * @param args
     */
    public static void main(String[] args) {
        // Sufficient test memory(Do not recycle soft references)
        //testSoftReferNOGc();
        // Insufficient test memory (recycle soft references)
        testSoftReferGc();
    }

    /**
     * Simulate sufficient memory
     */
    public static void testSoftReferNOGc() {
        Object obj1 = new Object();
        // Create soft reference
        SoftReference softRefer = new SoftReference<>(obj1);
        // Observe memory address
        System.out.println("obj1=" + obj1);
        System.out.println("softRefer=" + softRefer.get());
        // obj1 Create conditions that can be recycled
        obj1 = null;
        // gc recovery
        System.gc();
        // Look at the memory address again
        System.out.println("obj1=" + obj1);
        System.out.println("softRefer=" + softRefer.get());
    }

    /**
     * Out of analog memory
     * 1.Set small heap memory
     * 2.Create large objects
     * 3.jvm ginseng
     * -Xms5m -Xmx5m -XX:+PrintGCDetails
     */
    public static void testSoftReferGc() {
        Object obj1 = new Object();
        // Create soft reference
        SoftReference softRefer = new SoftReference<>(obj1);
        // Observe memory address
        System.out.println("obj1=" + obj1);
        System.out.println("softRefer=" + softRefer.get());
        // obj1 Create conditions that can be recycled
        obj1 = null;
        try {
            byte[] bytes = new byte[6 * 1024 * 1024];
        } catch (Throwable e) {
            System.out.println("===============>error:" + e.getMessage());
        } finally {
            // Look at the memory address again
            System.out.println("obj1=" + obj1);
            System.out.println("softRefer=" + softRefer.get());
        }
    }
}

Test result of sufficient memory:

Insufficient memory test results:

Actual case

If an application needs to read a large number of local data (pictures, communication rates, temporary files, etc.):

If the data is read from the hard disk every time, the performance will be seriously affected,

If all of them are loaded into memory at one time, it may cause memory overflow.

Using soft references can solve this problem.

The design idea is: use a HashMap to save the mapping relationship between the path of data and the soft reference associated with the corresponding data object. When the memory is insufficient,

The JVM automatically reclaims the space occupied by these cached data objects, thus effectively avoiding the problem of 00M.

Map<String,SoftReference>imageCache=new HashMap<String,SoftReference>();

3.3. What is weak quotation

a. Weak references are also used to describe unnecessary objects, but they are weaker than soft references. Objects associated with weak references can only survive until the next garbage collection.

b. . when the garbage collector is working, objects associated with only weak references will be recycled, regardless of whether the current memory is sufficient or not. After JDK 1.2, the wide week reference class is provided to implement weak references.

c. Weak references require Java.lang.ref.WeakReference class, which has a shorter lifetime than soft references

Case:

package com.wfd360.demo03GC.referDemo;

import java.lang.ref.WeakReference;

/**
 * @author Pose emperor blog Garden
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 12:12
 * @description
 */
public class WeakRefer {

    /**
     * Understanding of weak quotation
     *
     * @param args
     */
    public static void main(String[] args) {
        Object obj1 = new Object();
        // Building weak references
        WeakReference softRefer = new WeakReference<>(obj1);
        // Observe memory address
        System.out.println("obj1=" + obj1);
        System.out.println("softRefer=" + softRefer.get());
        // obj1 Create conditions that can be recycled
        obj1 = null;
        // gc recovery
        System.gc();
        // Look at the memory address again
        System.out.println("obj1=" + obj1);
        System.out.println("softRefer=" + softRefer.get());
    }

}

Extended knowledge - WeakHashMap

View API introduction:

Test code:

package com.wfd360.demo03GC.referDemo;

import java.util.HashMap;
import java.util.WeakHashMap;

/**
 * @author Pose emperor blog Garden
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 5:10
 * @description <p>
 * Weak reference: WeakHashMap
 * Hash table based Map implemented by weak key. In WeakHashMap, when a key is no longer in normal use, its entry is automatically removed.
 * More precisely, for a given key, the existence of its mapping does not prevent the garbage collector from discarding the key, which makes the key Terminable and terminated,
 * Then it's recycled. When a key is discarded, its entries are effectively removed from the Map, so the behavior of this class differs from other Map implementations.
 * </p>
 */
public class WeakReferMap {
    /**
     * Test the difference between HashMap and WeakHashMap
     * Test logic:
     * 1.Create different map s
     * 2.Create key value value
     * 3.Put in the respective map and print the results
     * 4.Set the key to null and print the result
     * 5.Manual GC and print results
     *
     * @param args
     */
    public static void main(String[] args) {
        hashMapMethod();
        System.out.println("--------Gorgeous dividing line--------");
        weakHashMapMethod();
    }

    /**
     * HashMap Test (strong reference)
     */
    private static void hashMapMethod() {
        HashMap<String, String> map = new HashMap<>();
        String key = "key1";
        String value = "HashMap-value";

        map.put(key, value);
        System.out.println(map);

        key = null;
        System.out.println(map);

        System.gc();
        System.out.println(map);
    }

    /**
     * If reference (WeakHashMap test)
     */
    private static void weakHashMapMethod() {
        WeakHashMap<String, String> map = new WeakHashMap<>();
        // Pay attention here new A string and direct write key="key2"The test results are different. For detailed reasons, see the memory allocation mentioned earlier
        String key = new String("key2");
        String value = "WeakHashMap-value";

        map.put(key, value);
        System.out.println(map);

        key = null;
        System.out.println(map);

        System.gc();
        System.out.println(map);

    }

}

Test results:

It can be seen from the test results that the map data with weak reference has been recycled.

Extended knowledge - ReferenceQueue reference queue

Code:

package com.wfd360.demo03GC.referDemo;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;

/**
 * @author Pose emperor blog Garden
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 7:23
 * @description
 */
public class QueueRefer {
    /**
     * Put the data in the queue before testing weak reference recovery
     *
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue();
        // When GC When freeing object memory, references are added to the reference queue
        WeakReference<Object> weakReference = new WeakReference<>(obj1, referenceQueue);

        System.out.println(obj1);
        System.out.println(weakReference.get());
        System.out.println(referenceQueue.poll());

        System.out.println("--------Gorgeous dividing line--------");
        obj1 = null;
        System.gc();
        Thread.sleep(500);

        System.out.println(obj1);
        System.out.println(weakReference.get());
        System.out.println(referenceQueue.poll());
    }

}

Test results by weak reference:

As you can see from the test results, the objects to be recycled have entered the queue.

Test results by soft reference:

It can be seen from the test results that the soft reference does not reach the recycling condition, does not recycle, and will not enter the queue;

3.4. What is virtual reference

1. Virtual reference needs java.lang.ref.PhantomReference class.

2. Unlike other references, virtual references do not determine the life cycle of an object. If an object only holds

Virtual reference, like no reference, can be recycled by the garbage collector at any time. It cannot be used alone or accessed through it

The virtual reference must be used in conjunction with the reference queue.

3. The main function of virtual reference is to track the status of garbage collection. It just provides a way to make sure that after the object is finalize d, it does something

Mechanism. The get method of PhantomReference always returns null, so the corresponding reference object cannot be accessed. Its significance lies in the explanation of an object

After entering the stage of finalization, it can be recycled by gc to achieve more flexible recycling operations than the finalization mechanism.

4. The only purpose of setting virtual reference association is to receive a system notification or subsequent addition when the object is recycled by the collector

Further processing. Java technology allows you to use the finalize() method to do the necessary cleanup before the garbage collector cleans objects out of memory.

code:

package com.wfd360.demo03GC.referDemo;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

/**
 * @author Pose emperor blog Garden
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 7:44
 * @description
 */
public class PhantomRefer {
    /**
     * Virtual reference test
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue();
        PhantomReference<Object> phantomReference = new PhantomReference<>(obj1,referenceQueue);

        System.out.println(obj1);
        System.out.println(phantomReference.get());
        System.out.println(referenceQueue.poll());

        System.out.println("--------Gorgeous dividing line--------");

        obj1 = null;
        System.gc();
        Thread.sleep(500);

        System.out.println(obj1);
        System.out.println(phantomReference.get());
        System.out.println(referenceQueue.poll());
    }

}

Test results:

4. Important summary

Process of judging whether the object is alive or not:

1. Reachability analysis, to see if there is a reference chain of GC Roots, if not, it will be marked for the first time;

2. Check whether the finalize() method needs to be executed,

If it is unnecessary (executed before), directly reclaim the memory;

If you want to execute the finalize() method, at this time, if the object establishes the reference chain again (the only self-help opportunity), the object will not be recycled, otherwise it will be recycled directly;

Summary:

1. Object recycling meets two conditions:

a. There is no reference chain.

b. Before recycling, the finalize() method will be executed. If the finalize() method is executed, no connection will be established again (if the connection is established with any object on the reference chain again, such as assigning an object value, the object will not be recycled)

2. The finalize() method will be executed only once before gc recycling, and asynchronous execution does not guarantee success, and the thread priority is low

Code demonstration:

package com.wfd360.demo03GC.referDemo;

/**
 * @author Pose emperor blog Garden
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 06/20 8:34
 * @description
 */
public class FinalizeGC {
    public static FinalizeGC obj1 = null;

    /**
     * Override finalize method
     * @throws Throwable
     */
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("implement finalize method");
        // save oneself,Establish a reference chain when recycling
        FinalizeGC.obj1 = this;
    }

    public static void main(String[] args) throws InterruptedException {
        obj1  = new FinalizeGC();

        obj1 = null;
        System.gc();
        Thread.sleep(600);
        System.out.println("First self rescue success:"+obj1);

        obj1 = null;
        System.gc();
        Thread.sleep(600);
        System.out.println("Second self rescue failure,Will not be executed again finalize method:"+obj1);
    }
}

Test results:

Perfect!

Keywords: Java jvm JDK

Added by chris_2001 on Sun, 21 Jun 2020 08:56:41 +0300