Java: diferencia entre strong / soft / weak / phantom reference

He leído este artículo sobre el tema, pero realmente no lo entiendo. Por favor, dame algunos consejos junto con ejemplos al describir los conceptos.

Java proporciona dos tipos / clases diferentes de objetos de referencia : fuerte y débil . Los objetos de referencia débiles se pueden dividir aún más en blando y fantasma . Vayamos punto por punto.

Objeto de referencia fuerte

StringBuilder builder = new StringBuilder(); 

Este es el tipo / clase por defecto del objeto de referencia, si no se especifica de otra manera: el builder es un fuerte objeto de referencia. Este tipo de referencia hace que el objeto al que se hace referencia no sea elegible para GC. Es decir, siempre que un objeto sea referenciado por una cadena de Objetos de Referencia fuertes , no se puede recolectar basura.

Objeto de referencia débil

 WeakReference weakBuilder = new WeakReference(builder); 

Los Objetos de Referencia Débiles no son el tipo / clase por defecto del Objeto de Referencia y para ser usados ​​deben ser explícitamente especificados como en el ejemplo anterior. Este tipo de referencia hace que el objeto de referencia sea elegible para GC. Es decir, en caso de que la única referencia alcanzable para el objeto StringBuilder en la memoria sea, en realidad, la referencia débil, entonces el GC puede recoger el objeto StringBuilder . Cuando un objeto en la memoria solo puede alcanzarse con Objetos de referencia débiles, se convierte automáticamente en elegible para GC.

Niveles de debilidad

Se pueden alistar dos niveles diferentes de debilidad: suave y fantasma .

Un objeto de referencia blando es básicamente un objeto de referencia débil que permanece en la memoria un poco más: normalmente resiste el ciclo del GC hasta que la memoria esté disponible y no hay riesgo de OutOfMemoryError (en ese caso, se puede eliminar).

Por otro lado, un objeto de referencia fantasma es útil solo para saber exactamente cuándo se ha eliminado efectivamente un objeto de la memoria: normalmente se utilizan para corregir el comportamiento de reavivamiento / resurrección finalize () extraño , ya que en realidad no devuelven el objeto en sí, pero solo ayuda a hacer un seguimiento de su presencia de memoria .

Los objetos de referencia débiles son ideales para implementar módulos de caché. De hecho, se puede implementar una especie de desalojo automático al permitir que el GC limpie las áreas de la memoria cuando los objetos / valores ya no son accesibles mediante una cadena de referencias sólida. Un ejemplo es el WeakHashMap que conserva claves débiles.

Débil referencia:

Una referencia débil, en pocas palabras, es una referencia que no es lo suficientemente fuerte como para obligar a un objeto a permanecer en la memoria. Las referencias débiles le permiten aprovechar la capacidad del recolector de basura para determinar la accesibilidad para usted, por lo que no tiene que hacerlo usted mismo.

Referencia suave:

Una referencia suave es exactamente como una referencia débil, excepto que está menos ansioso por tirar el objeto al que se refiere. Un objeto que solo es débilmente alcanzable (las referencias más fuertes a él son WeakReferences) se descartarán en el siguiente ciclo de recolección de elementos no utilizados, pero un objeto que se puede alcanzar suavemente generalmente se mantendrá durante un tiempo.

Referencia Phantom:

Una referencia fantasma es bastante diferente de SoftReference o WeakReference. Su control sobre su objeto es tan tenue que ni siquiera puede recuperar el objeto; su método get () siempre devuelve nulo. El único uso para dicha referencia es hacer un seguimiento de cuándo se pone en cola en una ReferenceQueue, ya que en ese momento sabes que el objeto al que apuntaba está muerto.

Este texto fue extraído de: https://weblogs.java.net/blog/2006/05/04/understanding-weak-references

La simple diferencia entre SoftReference y WeakReference es proporcionada por Android Developer .

La diferencia entre SoftReference y WeakReference es el punto en el que se toma la decisión de borrar y poner en cola la referencia:

  • Una SoftReference debe SoftReference y ponerse en SoftReference lo más tarde posible, es decir, en caso de que la máquina virtual corra peligro de quedarse sin memoria.

  • Una WeakReference puede WeakReference ponerse en WeakReference tan pronto como se sepa que tiene una referencia débil.

Los tres términos que ha usado se relacionan principalmente con la elegibilidad de Object para obtener la recolección de basura.

Weak Reference :: Es una referencia que no es lo suficientemente fuerte como para obligar al objeto a permanecer en la memoria. Son los caprichos del recolector de basura recolectar ese objeto para la recolección de basura. No puedes obligar a ese GC a no recogerlo .

Referencia suave :: Es más o menos lo mismo que la referencia débil. Pero puede decir que mantiene el objeto un poco más fuerte que la referencia débil de la recolección de basura.

Si los recolectores de basura recogen la referencia débil en el primer ciclo de vida en sí, recogerá la referencia suave en el próximo ciclo de recolección de basura.

Referencia fuerte :: Es justo lo contrario a los dos tipos de referencias anteriores. Son menos como obtener basura recolectada (en su mayoría nunca se recogen).

Puede consultar el siguiente enlace para obtener más información:

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html

4 grados de referencia: Strong, Weak, Soft, Phantom

Fuerte: es un tipo de referencia que hace que el objeto al que se hace referencia no sea elegible para GC. clases de constructor por ejemplo, StringBuilder

Débil – es una referencia que es elegible para GC.

Suave – es un tipo de referencia cuyo objeto es elegible para GC hasta que la memoria esté disponible. Lo mejor para la memoria caché de imágenes. Los mantendrá hasta que la memoria esté disponible.

Phantom: es un tipo de referencia cuyo objeto es directamente elegible para GC. Se usa solo para saber cuándo se elimina un objeto de la memoria.

usos:

  1. Le permite identificar cuándo un objeto se elimina exactamente de la memoria.

  2. Cuando el método finalize() está sobrecargado, entonces el GC podría no suceder de manera oportuna para los objetos GC elegibles de las dos clases. Así que la referencia fantasma los hace elegibles para GC antes de finalize() , es por eso que puedes obtener OutOfMemoryErrors incluso cuando la mayor parte del montón es basura.

Las referencias débiles son ideales para implementar los módulos de caché.

Referencias fuertes

Estas son sus referencias de objetos regulares que codificamos diariamente:

 Employee emp = new Employee(); 

La variable “emp” contiene una fuerte referencia a un objeto Employee y los objetos que se pueden alcanzar a través de cualquier cadena de referencias fuertes no son elegibles para la recolección de basura. Por lo general, esto es lo que quieres, pero no siempre. Ahora supongamos que estamos buscando a muchos empleados de la base de datos en una colección o mapa, y tenemos que hacer un montón de procesamiento en ellos regularmente, por lo que para mantener el rendimiento los mantendremos en el caché.

En lo que respecta a esto, es bueno, pero ahora necesitamos datos diferentes y no necesitamos esos objetos Employee y no se hace referencia a ellos desde ningún lugar, excepto el caché. ¿Qué está causando una pérdida de memoria porque estos objetos no están en uso pero aún no son elegibles para la recolección de basura y no podemos eliminar esos objetos de la memoria caché porque no tenemos referencia a ellos? Así que aquí, o bien tenemos que vaciar todo el caché de forma manual, lo cual es tedioso o podríamos utilizar otras referencias de tipo, por ejemplo, Referencias débiles.

Referencias Débiles

Una referencia débil no fija un objeto en la memoria y será GC en el próximo ciclo de GC si no se hace referencia a él desde otras referencias. Podemos usar la clase WeakReference que proporciona Java para crear el tipo de cachés anterior, que no almacenará objetos que no estén referenciados desde otro lugar.

 WeakReference cache = new WeakReference(data); 

Para acceder a los datos, debe llamar a cache.get (). Esta llamada a get puede devolver nulo si la referencia débil fue basura recolectada: debe verificar el valor devuelto para evitar NPE. Java proporciona colecciones que utilizan referencias débiles, por ejemplo, la clase WeakHashMap almacena claves (no valores) como referencias débiles. Si la clave está GC’d, el valor también se eliminará automáticamente del mapa.

Como las referencias débiles también son objetos, necesitamos una forma de limpiarlos (ya no son útiles cuando el objeto al que se refieren ha sido GC’d). Si transfiere una ReferenceQueue al constructor para obtener una referencia débil, el recolector de elementos no utilizados agregará esa referencia débil a ReferenceQueue antes de que se finalicen o se generen GC’d. Puede procesar esta cola periódicamente y tratar con referencias muertas.

Referencias suaves

Una SoftReference es como una WeakReference pero es menos probable que sea basura recolectada. Las referencias suaves se eliminan a discreción del recolector de basura en respuesta a la demanda de memoria. La máquina virtual garantiza que todas las referencias suaves a los objetos de acceso suave se habrán borrado antes de lanzar un OutOfMemoryError.

Referencias ficticias

Las referencias ficticias son las más débiles de todos los tipos de referencia, las llamadas para obtenerlas siempre devolverán nulos. Un objeto se referencia fantasma después de que se ha finalizado, pero antes de recuperar su memoria asignada, a diferencia de las referencias débiles que se ponen en cola antes de que se finalicen o las referencias Phantom GC’d se usan raramente.

Entonces, ¿cómo son útiles? Cuando construyes una referencia fantasma siempre debes pasar una ReferenceQueue. Esto indica que puede usar una referencia ficticia para ver cuándo su objeto está GC’d.

Oye, entonces si las referencias débiles se ponen en cola cuando se consideran finalizadas pero aún no se han generado GC, podríamos crear una nueva referencia fuerte al objeto en el bloque del finalizador y evitar que el objeto sea GC. Sí, puedes, pero probablemente no deberías hacer esto. Para verificar este caso, el ciclo GC ocurrirá al menos dos veces para cada objeto, a menos que ese objeto sea accesible solo mediante una referencia fantasma. Esta es la razón por la que puede quedarse sin stacks incluso cuando su memoria contiene mucha basura. Las referencias ficticias pueden evitar esto.

Intereting Posts