Notes on the WeakReference class in Java (weak reference)

Preface

When looking at the ThreadLocal source code today, the Entry in the internal class ThreadLocalMap inherited WeakReferenc. In order to figure out ThreadLocal, we can only understand WeakReferenc first.

First look at the source code:

It can be seen from the source code that it has inherited the abstract class Reference, WeakReference is literally, weak reference, when an object is only pointed to by a weak reference (weak reference), and there is no other strong reference (strong reference), if At this time GC is running, then the object will be recycled, regardless of whether the current memory space is sufficient, the object will be recycled.

WeakReference(T referent): referent is the weakly referenced object, which can be used as follows, and the reference is obtained through the get() method:

        Student student = new Student("hello");
        WeakReference<Student> appleWeakReference = new WeakReference<>(student);
        Student s = appleWeakReference.get();
        System.out.println(s);

WeakReference(T referent, ReferenceQueue<? super T> q): This construction method has an additional ReferenceQueue parameter. After the object is recycled, the weak reference object, that is, the WeakReference object or its subclasses, will be put into the queue ReferenceQueue Note that it is not the weakly referenced object, the weakly referenced object has been recycled.

The above is to use soft references by inheriting WeakReference, and do not use ReferenceQueue:

Create a new student class:

package com.zoo.api.modules.test.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;

/**
 * @author: 谢飞
 */
@Data
@AllArgsConstructor
@ToString
public class Student {
    private String name;

    /**
     * 覆盖finalize,在回收的时候会执行。
     */
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println(name + "对象正在回收finalize");
    }
}

The Person class that inherits WeakReference:

package com.zoo.api.modules.test.entity;

import java.lang.ref.WeakReference;

/**
 * 这里Person继承WeakReference,将Student作为弱引用。注意到时候回收的是Student,而不是Person
 *
 * @author: 谢飞
 */
public class Person extends WeakReference<Student> {
    public Person(Student referent) {
        super(referent);
    }
}

test:

    public static void main(String[] args) throws InterruptedException {
        Person person = new Person(new Student("张三"));
        //通过WeakReference的get()方法获取Apple
        System.out.println("Student:" + person.get());
        System.gc();
        //休眠一下,在运行的时候加上虚拟机参数-XX:+PrintGCDetails,输出gc信息,确定gc发生了。
        Thread.sleep(5000);
        System.out.println("gc回收之后的Student:" + person.get());
    }

Console print:

Student:Student(name=张三)
[GC (System.gc()) [PSYoungGen: 3939K->1240K(37888K)] 3939K->1248K(123904K), 0.0009368 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 1240K->0K(37888K)] [ParOldGen: 8K->1107K(86016K)] 1248K->1107K(123904K), [Metaspace: 3389K->3389K(1056768K)], 0.0037127 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
张三对象正在回收finalize
gc回收之后的Student:null
Heap
 PSYoungGen      total 37888K, used 4260K [0x00000000d6100000, 0x00000000d8b00000, 0x0000000100000000)
  eden space 32768K, 13% used [0x00000000d6100000,0x00000000d6529188,0x00000000d8100000)
  from space 5120K, 0% used [0x00000000d8100000,0x00000000d8100000,0x00000000d8600000)
  to   space 5120K, 0% used [0x00000000d8600000,0x00000000d8600000,0x00000000d8b00000)
 ParOldGen       total 86016K, used 1107K [0x0000000082200000, 0x0000000087600000, 0x00000000d6100000)
  object space 86016K, 1% used [0x0000000082200000,0x0000000082314f20,0x0000000087600000)
 Metaspace       used 3977K, capacity 4572K, committed 4864K, reserved 1056768K
  class space    used 435K, capacity 460K, committed 512K, reserved 1048576K

 From the above code, after executing gc, Student was indeed recycled.

Use of ReferenceQueue:

test:

public static void main(String[] args) throws InterruptedException {
        ReferenceQueue<Student> referenceQueue = new ReferenceQueue<>();
        WeakReference<Student> weakReference1 = new WeakReference<>(new Student("张三"), referenceQueue);
        WeakReference<Student> weakReference2 = new WeakReference<>(new Student("李四"), referenceQueue);

        //不会输出,因为没有回收被弱引用的对象,并不会加入队列中
        System.out.println("gc调用前的referenceQueue:" + referenceQueue.poll());
        System.out.println(weakReference1.get());
        System.out.println(weakReference2.get());

        System.out.println("=====调用gc=====");
        System.gc();

        Thread.sleep(5000);

        System.out.println("=====gc调用后=====");
        //下面两个输出为null,表示对象被回收了
        System.out.println(weakReference1.get());
        System.out.println(weakReference2.get());

        //输出结果,再次证明对象被回收了
        //如果使用继承的方式就可以包含其他信息了
        System.out.println("appleReferenceQueue中:" + referenceQueue.poll());
    }

It can be seen that in the queue (ReferenceQueue), there is no content before calling gc. After calling gc, the object is recycled, and weak reference objects weakReference1 and weakReference2 are put into the queue.

Regarding the other three types of citations, strong citations, soft citations, and false citations, you can learn more about them on Baidu.

The levels of Java 4 references from high to low are:

    Strong Reference> Soft Reference> Weak Reference> Phantom Reference

to sum up:

An important difference between Java and C/C++ is that Java does not require programmers to manually apply for or release memory . JVM helps us through GC (Garbage-Colletion) (GC is actually a thread that special users reclaim useless objects in Java heap memory) The garbage collection operation is completed, so the programmer does not have to worry about the release of memory, that is, there is no need to manually manage the life cycle of the object.

But this does not mean that Java programmers do not have to worry about memory problems at all. For example, we have new many objects, and the life cycle of each object is very long, so long that even if there is insufficient memory, the GC cannot recover it. Some objects to release more memory, which will eventually lead to OOM (Out-Of-Memory) errors.

 

 

Guess you like

Origin blog.csdn.net/qq_36850813/article/details/103066946