Explicación detallada de los cuatro tipos de referencia de Java (referencia fuerte, referencia suave, referencia débil, referencia virtual relacionada)

Después de JDK1.2, Java amplió el concepto de referencias y las dividió en cuatro tipos: referencia fuerte, referencia suave, referencia débil y referencia fantasma. Las cuatro citas son de intensidad decreciente. (Para obtener más información, consulte: Cuatro tipos de referencia en Java)

1. Referencia fuerte (StrongReference)
La referencia fuerte es la referencia más utilizada. Si un objeto tiene una referencia fuerte, el recolector de basura nunca lo reclamará. Cuando no hay suficiente espacio de memoria, la máquina virtual Java preferiría generar un error OutOfMemoryError y hacer que el programa finalice de manera anormal, en lugar de reciclar arbitrariamente objetos con fuertes referencias para resolver el problema de la memoria insuficiente. PD: Una referencia fuerte en realidad significa lo que normalmente queremos decir con A a = new A().
2. Referencia suave (SoftReference)
Si un objeto solo tiene una referencia suave, el espacio de memoria es suficiente y el recolector de basura no lo reclamará, si el espacio de memoria es insuficiente, se recuperará la memoria de estos objetos. Siempre que el recolector de basura no lo recopile, el programa puede utilizar el objeto. Se pueden utilizar referencias suaves para implementar el almacenamiento en caché sensible a la memoria (a continuación se proporciona un ejemplo).
Las referencias suaves se pueden usar junto con una cola de referencia (ReferenceQueue). Si el recolector de basura recicla el objeto al que hace referencia la referencia suave, la máquina virtual Java agregará la referencia suave a la cola de referencia asociada con ella.
3. Referencia débil
La diferencia entre una referencia débil y una referencia suave es que los objetos con solo referencias débiles tienen un ciclo de vida más corto. Durante el proceso del subproceso del recolector de basura que escanea el área de memoria bajo su jurisdicción, una vez que se encuentra un objeto con solo referencias débiles, su memoria se recuperará independientemente de si el espacio de memoria actual es suficiente. Sin embargo, dado que el recolector de basura es un subproceso de muy baja prioridad, es posible que no necesariamente encuentre rápidamente objetos con referencias débiles.
Las referencias débiles se pueden utilizar junto con una cola de referencia (ReferenceQueue). Si el objeto al que hace referencia la referencia débil se recolecta como basura, la máquina virtual Java agregará la referencia débil a la cola de referencia asociada.
4.Referencia fantasma
La "referencia virtual", como su nombre indica, es sólo de nombre. A diferencia de otros tipos de referencias, las referencias virtuales no determinan el ciclo de vida del objeto. Si un objeto contiene solo referencias fantasmas, el recolector de basura puede reclamarlo en cualquier momento como si no tuviera referencias.
Las referencias virtuales se utilizan principalmente para rastrear la actividad de los objetos que recicla el recolector de basura. Una diferencia entre referencias virtuales, referencias suaves y referencias débiles es que las referencias virtuales deben usarse junto con una cola de referencia (ReferenceQueue). Cuando el recolector de basura se está preparando para reciclar un objeto, si descubre que todavía tiene una referencia virtual, agregará la referencia virtual a la cola de referencia asociada con él antes de reciclar la memoria del objeto.

Cada tipo de referencia se explica en detalle a continuación.

1. Referencia fuerte (referencia fuerte)

Características de las citas fuertes:

  • 1. Las referencias fuertes pueden acceder directamente al objeto de destino;
  • 2. El sistema no reciclará el objeto señalado por el bloqueo de referencia fuerte en ningún momento. La JVM preferiría lanzar una excepción OOM que recuperar el objeto señalado por una referencia fuerte;
  • 3. Las aplicaciones potentes pueden provocar pérdidas de memoria;

Ejemplos de uso:

Cadena cadena = nueva cadena ("holapalabra");

La variable str apunta al espacio del montón donde se encuentra la instancia de StringBuffer y el objeto se puede operar a través de str.

2.Referencia suave

Las referencias suaves son el tipo de referencia más fuerte además de las referencias fuertes. Se utiliza para describir algunos objetos que son útiles pero no necesarios. Para los objetos asociados con referencias suaves, estos objetos se incluirán en el alcance del reciclaje para el segundo reciclaje antes de que ocurra una excepción de desbordamiento de memoria en el sistema. Si no hay suficiente memoria para este reciclaje, se generará una excepción de desbordamiento de memoria.

Las referencias suaves se pueden utilizar a través de java.lang.ref.SoftReference. La JVM no reciclará rápidamente un objeto que contenga una referencia suave. La JVM determinará cuándo recolectarlo en función del uso actual del montón. Cuando el uso del montón se acerque al umbral, los objetos de referencia suaves se reciclarán. Por lo tanto, se pueden utilizar referencias suaves para implementar cachés sensibles a la memoria.

La característica de SoftReference es que una de sus instancias guarda una referencia suave a un objeto Java. La existencia de la referencia suave no impide que el hilo de recolección de basura recicle el objeto Java. Es decir, una vez que SoftReference guarda una referencia suave a un objeto Java, antes de que el hilo basura recicle el objeto Java, el método get() proporcionado por la clase SoftReference devuelve una referencia fuerte al objeto Java. Una vez que el hilo basura recopila el objeto Java, el método get() devolverá nulo.

Ejemplos de uso:

Object obj = new Object();
SoftReference sf = new SoftReference<>(obj);
obj = null;
System.gc();

3. Referencia débil (Referencia débil)

Una referencia débil es un tipo de referencia más débil que una referencia suave. Durante la GC del sistema, siempre que se encuentre una referencia débil, el objeto se reciclará independientemente de si el espacio del montón del sistema es suficiente. En Java, puede utilizar la instancia java.lang.ref.WeakReference para guardar una referencia débil a un objeto Java.

Ejemplo de uso 1:

Object obj = new Object ();
WeakReference sf = new WeakReference(obj);
obj = null;

Ejemplo de uso 2:

En el código fuente de JDK, ThreadLoaclMap.Entry (para obtener más detalles, consulte: Causas de pérdidas de memoria causadas por ThreadLoacl )

Insertar descripción de la imagen aquí

Las referencias suaves y las referencias débiles son muy adecuadas para guardar datos de caché prescindibles. Si hace esto, cuando la memoria del sistema sea insuficiente, estos datos de caché se reciclarán sin provocar un desbordamiento de memoria. Cuando los recursos de memoria son suficientes, estos datos almacenados en caché pueden existir durante mucho tiempo, lo que acelera el sistema.

4.Referencia fantasma

Las referencias virtuales son las más débiles de todos los tipos. Un objeto que contiene una referencia virtual es casi lo mismo que no tener referencia y el recolector de basura puede reciclarlo en cualquier momento. Al intentar obtener una referencia sólida mediante el método get() de una referencia virtual, siempre falla. Además, las referencias virtuales deben usarse junto con la cola de referencia, que se utiliza para rastrear el proceso de recolección de basura.

Cuando el recolector de basura se está preparando para reciclar un objeto, si descubre que todavía tiene una referencia virtual, destruirá el objeto después de la recolección de basura y agregará la referencia virtual a la cola de referencia. El programa puede saber si el objeto al que se hace referencia será recolectado como basura determinando si se ha agregado una referencia virtual a la cola de referencia. Si el programa descubre que se ha agregado una referencia virtual a la cola de referencias, puede tomar las acciones necesarias antes de que se recupere la memoria del objeto al que se hace referencia.

Ejemplos de uso:

Object obj = new Object ();
ReferenceQueue referenceQueue = new ReferenceQueue<>();
PhantomReference pr = new PhantomReference<>(obj,referenceQueue);
obj = null;

Acerca de la extensión de la clase WeakHashMap

La clase WeakHashMap está en el paquete java.util. Implementa la interfaz Map y es una implementación de HashMap. Utiliza referencias débiles como solución de almacenamiento para datos internos. WeakHashMap es una aplicación típica de referencias débiles y puede usarse como una solución simple de tabla de caché.

Los siguientes dos fragmentos de código utilizan WeakHashMap y HashMap para guardar una gran cantidad de datos respectivamente:

public void test(){
    
    
    Map weakHashMap= new WeakHashMap();
    for (int i =0;i<10000;i++){
    
    
    	weakHashMap.put("key"+i,new byte[i]);
	}
}

Nota: Si las claves de WeakHashMap contienen referencias sólidas en el sistema, entonces WeakHashMap degenerará en un HashMap normal porque no todas las entradas se pueden limpiar automáticamente.

Fuente original: https://zhuanlan.zhihu.com/p/57452267

Supongo que te gusta

Origin blog.csdn.net/weixin_43828467/article/details/115397718
Recomendado
Clasificación