Hay 4 tipos de referencias en Java: StrongReference, SoftReference, WeakReference y PhantomReference (la legendaria referencia fantasma jaja),
Estos cuatro tipos de referencias están estrechamente relacionados con GC. Veamos sus definiciones y escenarios de uso uno por uno:
1. Referencia fuerte
StrongReference es la implementación de referencia predeterminada de Java. Sobrevivirá en la JVM el mayor tiempo posible cuando ningún objeto apunte a ella y se reciclará después de la ejecución de GC.
código java
Copie el código de código de la siguiente manera:
@Prueba
public void strongReference() {
Referente de objeto = nuevo Objeto();
/**
* Crear StrongReference mediante asignación
*/
Objeto strongReference = referente;
afirmarMismo(referente,referenciafuerte);
referente = nulo;
Sistema.gc();
/**
* StrongReference no se reciclará después de GC
*/
afirmarNotNull(referenciafuerte);
}
2. Referencia débil y mapa débil
WeakReference, como sugiere el nombre, es una referencia débil. Cuando el objeto referenciado ya no tiene una referencia fuerte en la JVM, la referencia débil se reciclará automáticamente después de GC.
Copie el código de código de la siguiente manera:
@Prueba
referencia débil pública vacía () {
Referente de objeto = nuevo Objeto();
WeakReference<Objeto>weakReference = new WeakReference<Objeto>(referente);
afirmarSame(referente, débilRerference.get());
referente = nulo;
Sistema.gc();
/**
* Una vez que no haya una referencia fuerte que apunte al referente, la referencia débil se reciclará automáticamente después de la GC
*/
afirmarNull(weakRerference.get());
}
WeakHashMap usa WeakReference como clave. Una vez que no hay una referencia fuerte a la clave, WeakHashMap eliminará automáticamente la entrada relevante después de GC.
Copie el código de código de la siguiente manera:
@Prueba
public void débilHashMap() lanza InterruptedException {
Map<Objeto, Objeto> débilHashMap = new WeakHashMap<Objeto, Objeto>();
Clave de objeto = nuevo objeto();
Valor del objeto = nuevo Objeto();
débilHashMap.put (clave, valor);
afirmarTrue(weakHashMap.containsValue(valor));
clave = nulo;
Sistema.gc();
/**
* Espere a que las entradas no válidas ingresen a ReferenceQueue para que puedan borrarse la próxima vez que se llame a getTable
*/
Hilo.dormir(1000);
/**
* Una vez que no haya una referencia fuerte a la clave, WeakHashMap eliminará automáticamente la entrada relevante después de GC
*/
afirmarFalse(weakHashMap.containsValue(valor));
}
3.Referencia suave
SoftReference tiene básicamente las mismas características que WeakReference. La mayor diferencia es que SoftReference retendrá la referencia el mayor tiempo posible hasta que la JVM se quede sin memoria antes de reciclarla (garantía de máquina virtual). Esta característica hace que SoftReference sea muy adecuada para aplicaciones de almacenamiento en caché.
Copie el código de código de la siguiente manera:
@Prueba
referencia suave pública vacía () {
Referente de objeto = nuevo Objeto();
SoftReference<Objeto> softRerference = new SoftReference<Objeto>(referente);
afirmarNotNull(softRerference.get());
referente = nulo;
Sistema.gc();
/**
* Las referencias suaves solo se reciclarán antes de jvm OutOfMemory, por lo que son muy adecuadas para aplicaciones de almacenamiento en caché
*/
afirmarNotNull(softRerference.get());
}
4. Referencia fantasma
Como protagonista de este artículo, Phantom Reference es muy diferente de WeakReference y SoftReference, porque su método get() siempre devuelve nulo, de donde proviene su nombre.
código java
Copie el código de código de la siguiente manera:
@Prueba
public void phantomReferenceAlwaysNull() {
Referente de objeto = nuevo Objeto();
PhantomReference<Objeto> phantomReference = new PhantomReference<Objeto>(referente, nuevo ReferenceQueue<Objeto>());
/**
* El método get de referencia fantasma siempre devuelve nulo
*/
afirmarNull(phantomReference.get());
}
Quizás se pregunte, ¿de qué sirve una referencia que siempre devuelve nulo? Preste atención al segundo parámetro ReferenceQueue al construir PhantomReference (de hecho, WeakReference y SoftReference también pueden tener este parámetro).
El único uso de PhantomReference es realizar un seguimiento de cuándo el referente se pone en cola en ReferenceQueue.
5. Cola de relevancia
Cuando una WeakReference comienza a devolver nulo, el objeto al que apunta está listo para ser reciclado. En este momento, se puede realizar algún trabajo de limpieza apropiado. Pase una ReferenceQueue al constructor de una Referencia. automáticamente El objeto se inserta en ReferenceQueue. WeakHashMap usa ReferenceQueue para borrar las entradas cuyas claves ya no tienen referencias sólidas.
código java
Copie el código de código de la siguiente manera:
@Prueba
public void referenceQueue() lanza InterruptedException {
Referente de objeto = nuevo Objeto();
ReferenceQueue<Objeto> referenceQueue = new ReferenceQueue<Objeto>();
WeakReference<Object>weakReference = new WeakReference<Object>(referente, referenceQueue);
afirmarFalse(weakReference.isEnqueued());
Referencia<? extiende Objeto> encuestado = referenceQueue.poll();
afirmarNull(encuestado);
referente = nulo;
Sistema.gc();
afirmarTrue(weakReference.isEnqueued());
Referencia<? extiende Objeto> eliminado = referenceQueue.remove();
afirmarNotNull (eliminado);
}
6. Referencia fantasma frente a referencia débil
PhantomReference tiene dos beneficios: primero, nos permite saber exactamente cuándo se elimina el objeto de la memoria. Esta función se puede usar para algunas necesidades especiales (como Distributed GC, XWork y google-guice también usan PhantomReference).
En segundo lugar, puede evitar algunos problemas fundamentales causados por la finalización. Como se mencionó anteriormente, la única función de PhantomReference es rastrear cuándo el referente se pone en cola en ReferenceQueue, pero WeakReference también tiene funciones correspondientes.
Se trata del método de finalización de Object. Este método se llamará antes de que se ejecute gc. Si un objeto sobrecarga el método de finalización y crea deliberadamente una fuerte referencia a sí mismo dentro del método, esto hará que esta ronda de GC no pueda realizarse. Reciclado Este objeto puede causar cualquier GC. El resultado final es que hay mucha basura en la JVM pero OutOfMemory. Este problema se puede evitar usando PhantomReference, porque PhantomReference está en proceso de finalización. Se recicla después de ejecutar el método, lo que significa que es imposible obtener la referencia original en este momento, por lo que el problema anterior no ocurrirá. Por supuesto, este es un ejemplo muy extremo y generalmente no ocurre.
7. Comparación
Referencias suaves, débiles y fantasmas | ||||
---|---|---|---|---|
Tipo | Objetivo | Usar | Cuando obtuvo la victoria | Clase de implementación |
Referencia fuerte | Una referencia ordinaria mantiene vivos los objetos mientras se haga referencia a ellos. | referencia normal. | Cualquier objeto que no sea señalado puede ser reclamado. | por defecto |
Referencia suave | Mantiene vivos los objetos siempre que haya suficiente memoria. | para mantener vivos los objetos incluso después de que los clientes hayan eliminado sus referencias (cachés sensibles a la memoria), en caso de que los clientes comiencen a solicitarlos nuevamente mediante clave. | Después de una primera pasada de gc, la JVM decide que aún necesita recuperar más espacio. | java.lang.ref.SoftReference |
Referencia débil | Mantiene los objetos vivos solo mientras están en uso (accesibles) para los clientes. | Contenedores que eliminan automáticamente objetos que ya no están en uso. | Después de que gc determina que el objeto es sólo débilmente accesible | java.lang.ref.WeakReference java.util.WeakHashMap |
Referencia fantasma | Le permite limpiar después de la finalización pero antes de que se recupere el espacio (reemplaza o aumenta el uso de finalizar()) | Procesamiento de limpieza especial | Después de la finalización. | java.lang.ref.PhantomReferencia |
8. Resumen
Las aplicaciones generales no implicarán programación de referencia, pero comprender este conocimiento será útil para comprender el principio de funcionamiento de GC y el ajuste del rendimiento. También se puede utilizar al implementar algunas funciones básicas como el almacenamiento en caché.