Explain the four references of Java-strong and weak, subvert your cognition!

Strong and weak

Data in java is divided into two types by types, which are basic types and reference types. Generally, our new objects belong to the category of reference types. We know that Java is a language with a garbage collection mechanism. According to the garbage collection strategy, Java further subdivides the references to heap objects. References are divided into strong references, soft references, weak references and virtual references.

Strong citation

Strong reference, also known as ordinary reference, is the most common type of reference. Generally, when we newcreate an object through keywords, the reference of the variable to the heap object is a strong reference.
Insert picture description here
The characteristics of strong citation:

  • If an object in the heap is pointed to by a strong reference, then this variable will not be collected by the GC.
  • In the case of insufficient heap memory, the object pointed to by the strong reference will not be recycled. (Prefer to throw OOM exception)
  • Objects pointed to by strong references will be collected by the GC only after the references disappear.

Test code-1:

/* 这个类用于申请堆内存 */
public class Memory {
    private byte[] alloc;

    public Memory(int size) { this.alloc = new byte[size]; }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("被GC回收");
    }
}

 

public class Normal {
    public static void main(String[] args) throws InterruptedException {

        /* 栈变量m对new出来的Memory对象的引用为强引用 */
        Memory m = new Memory(1024 * 1024 * 20);

        /* 现在堆中的对象没有引用指向它,它要被GC回收 */
        m = null;

        System.gc(); /* 显式GC */

        /*
         * 当我们启动java程序时,默认会有两个线程,一个是我们的主线程,另一个便是GC线程。
         * 通常GC线程的优先级比较低,并且GC线程默认为守护线程,即它会在主线程退出的同
            * 时退出。
         *
         * 为了观察到GC的效果,我们让主线程休眠1s
         */
        Thread.sleep(1000);
    }

}

Test result-1:
Insert picture description here
Test code-2

public class Normal {

    public static void main(String[] args) throws InterruptedException {

        /* 我们设定JVM参数,设置堆内存大小为25MB */


        /* 栈变量m1对new出来的Memory对象的引用为强引用 */

        /* 申请了20MB的内存,实际会大于20MB,因为我们的byte[]被Memory对象wrapper */
        Memory m1 = new Memory(1024 * 1024 * 20);

        System.gc();
        Thread.sleep(1000);

        /* 再申请10MB堆内存 */
        Memory m2 = new Memory(1024 * 1024 * 10);
    }

}

Test result-2
Insert picture description here

Soft reference

The creation of soft references needs java.lang.ref.SoftReferenceto be created with the help of this class in jdk . In other words, our variable is first referenced to the SoftReference object, and then the SofReference object is used to reference the object we want to set as a soft reference.
Insert picture description here
The characteristics of soft references

  • When the heap memory is enough, the object pointed to by the soft reference will not be reclaimed by the GC.
  • When the heap memory is not enough, the object pointed to by the soft reference is automatically reclaimed by the GC.

Test code-3

public class Soft_Ref {

    public static void main(String[] args) throws InterruptedException {
        /* 堆内存大小为50MB */
        /* 申请30MB */
        SoftReference<Memory> m1 = new SoftReference<>(new Memory(1024 * 1024 * 30));

        System.gc(); /* 显示调用GC */

        /* 此时内存够用,所以结果可以预见性的为GC不会回收被软引用指向的对象 */

        Thread.sleep(1000);
    }
}

 Test result-3
Insert picture description here
test code-4

public class Soft_Ref {
    public static void main(String[] args) throws InterruptedException {

        /* 堆内存大小为50MB */

        /* 申请30MB */
        SoftReference<Memory> m1 = new SoftReference<>(new Memory(1024 * 1024 * 30));


        /* 申请20MB */
        for (int i = 0; i < 20; ++i) {
            System.out.println("[time] => " + System.currentTimeMillis());
            SoftReference<Memory> ma = new SoftReference<>(new Memory(1024 * 1024));
            Thread.sleep(200);
        }
    }
}

Test result-4
Insert picture description here

It can be seen from the test results that when the memory is insufficient or will be insufficient, the GC will be triggered, and the GC will automatically reclaim those soft references to the objects.

It must be noted that the recovery of the object pointed to by the soft reference will only be recovered when the GC is triggered. If the memory is sufficient, even if the GC is explicitly called, the object pointed to by the soft reference will not be recovered.

Weak reference

The method of creating weak references is similar to soft references, and requires the help of java.lang.ref.WeakReferenceclasses in jdk to create them.
Insert picture description here
Characteristics of weak references:

  • Regardless of the situation, the object pointed to by the weak reference will be recycled when the GC is encountered.

Test code-5

public class Weak_Ref {

    public static void main(String[] args) throws InterruptedException {
        /* 堆内存没有设置大小,为默认状态 */
        WeakReference<Memory> m = new WeakReference<>(new Memory(1024 * 1024 * 10));
        System.gc(); /* 调用GC */
        Thread.sleep(1000);
    }
}
测试结果-5

Phantom reference

Phantom reference is a very special kind of reference. It is mainly used for the management of off-heap memory. Phantom references can point to objects in the heap, but they have no practical meaning.
Insert picture description here
Insert picture description here
Features of false references:

  • Unable to get the value of the object pointed to by the phantom reference.
  • Phantom references will be notified when they are collected by the GC.
  • When a phantom reference encounters a GC, it will be collected by the GC regardless of whether there are any objects referencing it.

Test code-6

 

public class Phantom_Ref {
    static final ArrayList<byte[]> LIST = new ArrayList<>();

    static final ReferenceQueue<Memory> QUEUE = new ReferenceQueue<>();

    public static void main(String[] args) throws InterruptedException {

        PhantomReference<Memory> m = new PhantomReference<>(new Memory(1024 * 1024 * 10), QUEUE);
        new Thread(()->{
            while (true) {
                LIST.add(new byte[1024 * 1024 ]);

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
                System.out.println(m.get()); /* 虚引用指向的值永远无法被获取 */
            }
        }).start();

        new Thread(()->{
            while (true) {
                Reference<? extends Memory> poll = QUEUE.poll();
                if (poll != null) {
                    /* 虚引用在对象回收时,会进行通知 */
                    System.out.println("有虚引用被GC回收了-" + poll);
                    break;
                }
            }
        }).start();
    }
}

Test result-6
Insert picture description here

The above are the four references of Java compiled by the editor. They are just some personal understandings. There are some inaccuracies. Please point out that the editor and everyone will make progress together! ! !

Guess you like

Origin blog.csdn.net/a159357445566/article/details/108588947