Notas sobre la clase WeakReference en Java (referencia débil)

Prefacio

Al mirar el código fuente de ThreadLocal hoy, la entrada en la clase interna ThreadLocalMap heredó WeakReferenc. Para descubrir ThreadLocal, solo podemos entender primero WeakReferenc.

Primero mira el código fuente:

Se puede ver en el código fuente que ha heredado la clase abstracta Reference, WeakReference es literalmente, una referencia débil, cuando un objeto solo es apuntado por una referencia débil (referencia débil), y no hay otra referencia fuerte (referencia fuerte), si En este momento, GC se está ejecutando, el objeto se reciclará, independientemente de si el espacio de memoria actual es suficiente, el objeto se reciclará.

WeakReference (T referente): referente es el objeto débilmente referenciado, que se puede usar de la siguiente manera, y la referencia se obtiene mediante el método get ():

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

WeakReference (T referente, ReferenceQueue <? Super T> q): este método de construcción tiene un parámetro ReferenceQueue adicional. Después de que el objeto se recicla, el objeto de referencia débil, es decir, el objeto WeakReference o sus subclases, se colocará en la cola ReferenceQueue Tenga en cuenta que no es el objeto de referencia débil, el objeto de referencia débil se ha reciclado.

Lo anterior es usar referencias suaves heredando WeakReference y no use ReferenceQueue:

Crea una nueva clase para estudiantes:

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");
    }
}

La clase Person que hereda 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);
    }
}

prueba:

    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());
    }

Impresión de consola:

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

 A partir del código anterior, después de ejecutar gc, Student fue reciclado.

Uso de ReferenceQueue:

prueba:

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());
    }

Se puede ver que en la cola (ReferenceQueue), no hay contenido antes de llamar a gc. Después de llamar a gc, el objeto se recicla y los objetos de referencia débiles débilesReference1 y débilesReference2 se colocan en la cola.

Con respecto a los otros tres tipos de citas, citas fuertes, citas suaves y citas falsas, puede obtener más información sobre ellas en Baidu.

Los niveles de referencias de Java 4 de mayor a menor son:

    Referencia fuerte> Referencia suave> Referencia débil> Referencia fantasma

para resumir:

Una diferencia importante entre Java y C / C ++ es que Java no requiere que los programadores soliciten o liberen memoria manualmente . JVM nos ayuda a través de GC (Garbage-Colletion) (GC es en realidad un hilo que los usuarios especiales reclaman objetos inútiles en la memoria del montón de Java) La operación de recolección de basura se completa, por lo que el programador no tiene que preocuparse por la liberación de memoria, es decir, no es necesario administrar manualmente el ciclo de vida del objeto.

Pero esto no significa que los programadores de Java no tengan que preocuparse en absoluto por los problemas de memoria. Por ejemplo, tenemos muchos objetos nuevos y el ciclo de vida de cada objeto es muy largo, tanto que incluso si no hay memoria suficiente, el GC no puede recuperarlo. Algunos objetos para liberar más memoria, lo que eventualmente conducirá a errores OOM (Out-Of-Memory).

 

 

Supongo que te gusta

Origin blog.csdn.net/qq_36850813/article/details/103066946
Recomendado
Clasificación