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.
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.
Respuestas:
Java proporciona dos tipos / clases diferentes de objetos de referencia : fuertes y débiles . Los objetos de referencia débiles se pueden dividir en soft y phantom .
Vamos punto por punto.
Objeto de referencia fuerte
StringBuilder builder = new StringBuilder();
Este es el tipo / clase predeterminado del Objeto de referencia, si no se especifica de manera diferente: builder
es un Objeto de referencia fuerte. Este tipo de referencia hace que el objeto referenciado no sea elegible para GC. Es decir, cuando un objeto es referenciado por un cadena de objetos de referencia fuertes hace referencia a , no se puede recolectar basura.
Objeto de referencia débil
WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);
Los Objetos de referencia débiles no son el tipo / clase predeterminado de Objeto de referencia y, para ser utilizados, deben especificarse explícitamente 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 elStringBuilder
objeto en la memoria sea, en realidad, la referencia débil, entonces el GC puede recolectar basuraStringBuilder
objeto. Cuando un objeto en memoria es accesible solo por Objetos de referencia débiles, se convierte automáticamente elegible para GC.
Niveles de debilidad
Se pueden alistar dos niveles diferentes de debilidad: suave y fantasma .
Un suave objeto de referencia es básicamente un objeto de referencia débil que permanece un poco más en la memoria: normalmente, resiste el ciclo de GC hasta que no hay memoria disponible y existe el riesgo deOutOfMemoryError
(en ese caso, se puede eliminar).
Por otro lado, un Objeto de referencia fantasma es útil solo para saber exactamente cuándo un objeto se ha eliminado efectivamente de la memoria: normalmente se utilizan para corregir el comportamiento extraño de reactivación / resurrección finalize () , ya que en realidad no devuelven el objeto en sí, sino solo ayuda en el seguimiento de su presencia en la 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 memoria siempre que los objetos / valores ya no sean accesibles mediante una fuerte cadena de referencias. Un ejemplo es el WeakHashMap que retiene claves débiles.
Referencia débil:
Una referencia débil, simplemente, 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 ansiosa por tirar el objeto al que se refiere. Un objeto al que solo se puede llegar débilmente (las referencias más fuertes a él son WeakReferences) se descartará en el próximo ciclo de recolección de basura, pero un objeto al que se puede acceder suavemente generalmente se quedará por un tiempo.
Referencia fantasma:
Una referencia fantasma es bastante diferente de SoftReference o WeakReference. Su agarre 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 realizar un seguimiento de cuándo se pone en cola en un ReferenceQueue, ya que en ese momento sabe que el objeto al que apunta está muerto.
Este texto fue extraído de: https://weblogs.java.net/blog/2006/05/04/understanding-weak-references
La diferencia simple entre SoftReference
y WeakReference
es proporcionada por el desarrollador de Android .
La diferencia entre ay SoftReference
a WeakReference
es el momento en el que se toma la decisión de aclarar y poner en cola la referencia:
A se SoftReference
debe borrar y poner en cola lo más tarde posible, es decir, en caso de que la VM esté en peligro de quedarse sin memoria.
A WeakReference
se puede borrar y poner en cola tan pronto como se sepa que tiene una referencia débil.
Los tres términos que ha utilizado se relacionan principalmente con la elegibilidad de Object para recolectar basura.
Referencia débil :: Es una referencia que no es lo suficientemente fuerte como para obligar al objeto a permanecer en la memoria. Es el capricho de coleccionista de basura para recoger ese objeto para la recolección de basura. No puede obligar a ese GC a no recogerlo .
Referencia suave :: Es más o menos igual 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 recopilan la referencia débil en el primer ciclo de vida, la recopilación de la referencia flexible se realizará en el siguiente ciclo de recolección de basura.
Referencia fuerte :: Es justo opuesto a los dos tipos de referencias anteriores. Son menos propensos a que se recolecte basura (en su mayoría, nunca se recolectan).
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
Este artículo puede ser muy útil para comprender referencias fuertes, suaves, débiles y fantasmas.
Para darle un resumen,
Si tiene una referencia fuerte a un objeto, GC (Recolector de basura) nunca podrá recolectar / reclamar el objeto.
Si solo tiene referencias débiles a un objeto (sin referencias fuertes), entonces el objeto será reclamado por GC en el próximo ciclo de GC.
Si solo tiene referencias suaves a un objeto (sin referencias fuertes), entonces el objeto será reclamado por GC solo cuando JVM se quede sin memoria.
Creamos referencias fantasmas a un objeto para realizar un seguimiento de cuándo el objeto se pone en cola en el ReferenceQueue
. Una vez que sepa que puede realizar una finalización detallada. (Esto te salvaría de resucitar accidentalmente el objeto ya que la referencia fantasma no te da el referente). Le sugiero que lea este artículo para obtener detalles detallados sobre esto.
Entonces puedes decir que, las referencias fuertes tienen el máximo poder (nunca puede ser recolectado por GC)
Las referencias suaves son poderosas que las referencias débiles (ya que pueden escapar del ciclo de GC hasta que JVM se quede sin memoria)
Las referencias débiles son incluso menos potentes que las referencias suaves (ya que no pueden escapar de ningún ciclo de GC y se recuperarán si el objeto no tiene otra referencia fuerte).
Analogía de restaurantes
Ahora si eres un cliente fuerte (análogo a una referencia fuerte), incluso si un nuevo cliente entra en el restaurante o lo que sea que sea feliz, nunca dejará su mesa (el área de memoria en el montón). El camarero no tiene derecho a decirle (o incluso pedirle) que abandone el restaurante.
Si usted es un cliente flexible (análogo a una referencia flexible), si un nuevo cliente entra al restaurante, el camarero no le pedirá que abandone la mesa a menos que no quede otra mesa vacía para acomodar al nuevo cliente. (En otras palabras, el camarero le pedirá que abandone la mesa solo si un nuevo cliente interviene y no queda otra mesa para este nuevo cliente)
Si usted es un cliente débil (análogo a una referencia débil), entonces el camarero, a su voluntad, puede (en cualquier momento) pedirle que salga del restaurante: P
4 grados de referencia Strong, Weak, Soft, Phantom
Fuerte: es un tipo de referencia que hace que el objeto referenciado no sea elegible para GC. Clases de constructor. por ejemplo, StringBuilder
Débil: es una referencia elegible para GC.
Soft: es un tipo de referencia cuyo objeto es elegible para GC hasta que la memoria esté disponible. Lo mejor para el caché de imágenes. Los retendrá hasta que la memoria esté disponible.
Fantasma: es un tipo de referencia cuyo objeto es directamente elegible para GC. Solo se usa para saber cuándo se elimina un objeto de la memoria.
usos:
Le permite identificar cuándo un objeto se elimina exactamente de la memoria.
cuando el
finalize()
método está sobrecargado, es posible que GC no suceda de manera oportuna para los objetos elegibles para GC de las dos clases. Entonces, la referencia fantasma los hace elegibles para GC antesfinalize()
, es por eso que puede 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é.
Estas son sus referencias de objetos regulares que codificamos diariamente:
Employee emp = new Employee();
La variable "emp" contiene una referencia fuerte a un objeto Empleado y los objetos a los que se puede acceder 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 obteniendo muchos empleados de la base de datos en una colección o mapa, y necesitamos procesar mucho en ellos regularmente, por lo tanto, para mantener el rendimiento, los mantendremos en el caché.
En la medida en que esto sea bueno, pero ahora necesitamos datos diferentes y no necesitamos esos objetos Empleado y no se hace referencia a ellos desde ninguna parte, 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 del caché porque no tenemos referencia a ellos? Entonces, aquí o necesitamos vaciar todo el caché manualmente, lo cual es tedioso o podríamos usar otras referencias amables, por ejemplo, Referencias débiles.
Una referencia débil no fija un objeto en la memoria y será GC'd en el próximo ciclo de GC si no se hace referencia desde otras referencias. Podemos usar la clase WeakReference que proporciona Java para crear los tipos de cachés anteriores, que no almacenarán objetos a los que no se haga referencia desde otro lugar.
WeakReference<Cache> cache = new WeakReference<Cache>(data);
Para acceder a los datos, debe llamar a cache.get (). Esta llamada a get puede devolver nulo si la referencia débil era recolección de basura: debe verificar el valor devuelto para evitar NPE. Java proporciona colecciones que usan referencias débiles, por ejemplo, la clase WeakHashMap almacena claves (no valores) como referencias débiles. Si la clave es GC'd, el valor también se eliminará automáticamente del mapa.
Dado que las referencias débiles también son objetos, necesitamos una forma de limpiarlas (ya no son útiles cuando el objeto al que estaban haciendo referencia ha sido GC'd). Si pasa un ReferenceQueue al constructor para una referencia débil, entonces el recolector de basura agregará esa referencia débil al ReferenceQueue antes de que finalicen o GC'd. Puede procesar periódicamente esta cola y lidiar con referencias muertas.
Una SoftReference es como una WeakReference pero es menos probable que se recolecte basura. Las referencias suaves se borran 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 objetos accesibles de forma suave se hayan borrado antes de que arroje un OutOfMemoryError.
Las referencias fantasmas son las más débiles de todos los tipos de referencia, llamar a get on siempre devolverá nulo. Se hace referencia fantasma a un objeto después de que se ha finalizado, pero antes de que se haya recuperado su memoria asignada, a diferencia de las referencias débiles que se ponen en cola antes de que se finalicen o las referencias fantasmas GC'd rara vez se usen.
Entonces, ¿cómo son útiles? Cuando construye una referencia fantasma, siempre debe pasar un ReferenceQueue. Esto indica que puede usar una referencia fantasma para ver cuándo su objeto es GC'd.
Oye, así que si las referencias débiles se ponen en cola cuando se consideran finalizadas pero aún no GC'd, podríamos crear una nueva referencia fuerte al objeto en el bloque finalizador y evitar que el objeto sea GC'd. 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 por una referencia fantasma. Esta es la razón por la que puede quedarse sin almacenamiento dinámico incluso cuando su memoria contiene mucha basura. Las referencias fantasmas pueden evitar esto.
Puede leer más en mi artículo Tipos de referencias en Java (Strong, Soft, Weak, Phantom) .