¿Cuál es la diferencia entre java.lang.ref.WeakReference
y java.lang.ref.SoftReference
?
java
reference
weak-references
soft-references
driekken
fuente
fuente
Respuestas:
De Comprender las referencias débiles , de Ethan Nicholas:
Y Peter Kessler agregó en un comentario:
fuente
Las referencias débiles se recopilan con entusiasmo. Si GC encuentra que un objeto es débilmente accesible (accesible solo a través de referencias débiles), borrará las referencias débiles a ese objeto inmediatamente. Como tal, son buenos para mantener una referencia a un objeto para el cual su programa también guarda (fuertemente referenciada) "información asociada" en algún momento, como información de reflexión en caché sobre una clase, o un contenedor para un objeto, etc. Cualquier cosa que haga no tiene sentido guardarlo después de que el objeto al que está asociado sea GC-ed. Cuando la referencia débil se borra, se pone en cola en una cola de referencia que su código sondea en algún lugar, y también descarta los objetos asociados. Es decir, mantiene información adicional sobre un objeto, pero esa información no es necesaria una vez que el objeto al que hace referencia desaparece. Realmente, en ciertas situaciones, incluso puede subclasificar WeakReference y mantener la información adicional asociada sobre el objeto en los campos de la subclase WeakReference. Otro uso típico de WeakReference es en conjunción con Maps para mantener instancias canónicas.
SoftReferences, por otro lado, son buenos para almacenar en caché recursos externos y recreables, ya que el GC generalmente demora en borrarlos. Sin embargo, se garantiza que todas las SoftReferences se borrarán antes de que se arroje OutOfMemoryError, por lo que en teoría no pueden causar un OOME [*].
Un ejemplo de caso de uso típico es mantener una forma analizada de un contenido de un archivo. Implementaría un sistema donde cargaría un archivo, lo analizaría y mantendría una SoftReference al objeto raíz de la representación analizada. La próxima vez que necesite el archivo, intentará recuperarlo a través de SoftReference. Si puede recuperarlo, se ahorró otra carga / análisis, y si el GC lo borró mientras tanto, lo vuelve a cargar. De esa manera, utiliza memoria libre para la optimización del rendimiento, pero no se arriesga a un OOME.
Ahora para el [*]. Mantener una SoftReference no puede causar un OOME en sí mismo. Si, por otro lado, utiliza por error SoftReference para una tarea, se debe utilizar una WeakReference (es decir, si mantiene la información asociada a un Objeto fuertemente referenciada y la descarta cuando el objeto de Referencia se borra), puede ejecutar OOME como su código que sondea el ReferenceQueue y descarta los objetos asociados podría no ejecutarse de manera oportuna.
Por lo tanto, la decisión depende del uso: si está almacenando en caché información que es costosa de construir, pero no obstante reconstruible a partir de otros datos, use referencias suaves, si mantiene una referencia a una instancia canónica de algunos datos, o si desea tenga una referencia a un objeto sin "poseerlo" (evitando así que sea GC'd), use una referencia débil.
fuente
WeakReference
es que en los lugares donde uno debería usarlo, el hecho de que uno pueda permanecer válido durante un tiempo después de que la referencia salga del alcance puede ser tolerable, pero no es deseable.WeakReference
cual es observar las ejecuciones de GC. Ver elaboración: stackoverflow.com/a/46291143/632951En java ; orden de más fuerte a más débil, hay: fuerte, suave, débil y fantasma
Una referencia fuerte es una referencia normal que protege el objeto referido de la colección por GC. es decir, nunca se acumula basura.
Una referencia suave es elegible para la recolección por parte del recolector de basura, pero probablemente no se recolectará hasta que se necesite su memoria. es decir, la basura se acumula antes
OutOfMemoryError
.Una referencia débil es una referencia que no protege un objeto referenciado de la colección por GC. es decir, la basura se acumula cuando no hay referencias fuertes o suaves.
Una referencia fantasma es una referencia a un objeto al que se hace referencia fantasma una vez que se ha finalizado, pero antes de que se haya recuperado su memoria asignada.
Fuente
Analogía: suponga que una JVM es un reino, Object es un rey del reino y GC es un atacante del reino que intenta matar al rey (objeto).
fuente
until memory is available
no tiene sentido. Qué quiere deciris eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use
?Referencia débil http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html
Principio:
weak reference
está relacionado con la recolección de basura. Normalmente, los objetos que tienen uno o másreference
no serán elegibles para la recolección de basura.El principio anterior no es aplicable cuando lo es
weak reference
. Si un objeto solo tiene una referencia débil con otros objetos, entonces está listo para la recolección de basura.Veamos el siguiente ejemplo: Tenemos un
Map
con objetos donde Key es referencia a un objeto.Ahora, durante la ejecución del programa que hemos realizado
emp = null
. MantenerMap
presionada la tecla no tiene sentido aquí tal como esnull
. En la situación anterior, el objeto no es basura recolectada.WeakHashMap
WeakHashMap
es uno donde las entradas (key-to-value mappings
) se eliminarán cuando ya no sea posible recuperarlas delMap
.Permítanme mostrar el mismo ejemplo anterior con WeakHashMap
Salida: Tomó
20 calls to System.gc()
como resultado enaMap size
: 0.WeakHashMap
solo tiene referencias débiles a las teclas, no referencias fuertes como otrasMap
clases. Hay situaciones que debe tener cuidado cuando el valor o la clave están fuertemente referenciados a pesar de haberlo utilizadoWeakHashMap
. Esto se puede evitar envolviendo el objeto en una WeakReference .Referencias suaves
Soft Reference
Es ligeramente más fuerte que la referencia débil. La referencia suave permite la recolección de basura, pero le pide al recolector de basura que la limpie solo si no hay otra opción.El recolector de basura no recolecta de manera agresiva los objetos que se pueden alcanzar suavemente como lo hace con los que se pueden alcanzar débilmente; en cambio, solo recolecta los objetos que se pueden alcanzar suavemente si realmente "necesita" la memoria. Las referencias suaves son una forma de decirle al recolector de basura: "Mientras la memoria no sea demasiado apretada, me gustaría mantener este objeto cerca. Pero si la memoria se pone muy apretada, adelante, recójala y me ocuparé con ese." Se requiere que el recolector de basura borre todas las referencias suaves antes de poder lanzar
OutOfMemoryError
.fuente
NullPointerException
enaMap.get().put(...)
.WeakHashMap
ejemplo (ya que es el primero que demuestra un comportamiento Débil). Vistazo a doc para "WeakHashMap":"An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. "
El punto de usar WeakHashMap todo es que usted no tiene que declarar / de acceso en un WeakReference; WeakHashMap lo hace internamente. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.htmlWeakHashMap
en acción, con la aplicación de ejemplo que muestra cómo se eliminan las entradas solo después de que se ejecuta la recolección de basura, consulte mi Respuesta a la pregunta, ¿WeakHashMap está creciendo constantemente o borra las claves de basura? .La única diferencia real entre una referencia suave y una referencia débil es que
fuente
SoftReference
Está diseñado para cachés. Cuando se descubre que un objeto haceWeakReference
referencia a un objeto inalcanzable, se borrará de inmediato.SoftReference
puede dejarse como está. Por lo general, hay algún algoritmo relacionado con la cantidad de memoria libre y el último tiempo utilizado para determinar si se debe borrar. El algoritmo actual de Sun es borrar la referencia si no se ha utilizado en tantos segundos como haya megabytes de memoria libre en el almacenamiento dinámico de Java (configurable, el HotSpot del servidor verifica con el almacenamiento dinámico máximo establecido por-Xmx
).SoftReference
s se borrará antes de queOutOfMemoryError
se lance, a menos que se pueda acceder de otra manera.fuente
java.lang
. Tal abuso de sinónimos no le está haciendo ningún bien a nadie.Este artículo puede ser muy útil para comprender referencias fuertes, suaves, débiles y fantasmas.
Para darle un resumen,
Si solo tienes 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.
Entonces puedes decir que las referencias fuertes tienen el poder supremo (nunca puede ser recolectado por GC)
Las referencias suaves son poderosas que las 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 usted es 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 eres un cliente suave (análogo a una referencia flexible), si un cliente nuevo 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), el camarero, a su voluntad, puede (en cualquier momento) pedirle que salga del restaurante: P
fuente
La única diferencia real
Según el documento , un GC en ejecución debe eliminar las referencias débiles sueltas .
Según el documento , las SoftReferences sueltas deben borrarse antes de lanzar OOM.
Esa es la única diferencia real. Todo lo demás no es parte del contrato. (Asumiré que los últimos documentos son contractuales).
SoftReferences son útiles. Las memorias caché sensibles a la memoria usan SoftReferences, no WeakReferences.
El único uso apropiado de WeakReference es observar la ejecución del GC. Para ello, crea una nueva WeakReference cuyo objeto salga inmediatamente del alcance y luego intente salir de nulo
weak_ref.get()
. Cuando es asínull
, aprende que entre esta duración, el GC se ejecutó.En cuanto al uso incorrecto de WeakReference, la lista es interminable:
un truco pésimo para implementar la softreferencia de prioridad 2 de modo que no tenga que escribir una, pero no funciona como se esperaba porque la memoria caché se borrará en cada ejecución del GC, incluso cuando haya memoria de sobra. Consulte https://stackoverflow.com/a/3243242/632951 para ver las copias. (Además, ¿qué pasa si necesita más de 2 niveles de prioridad de caché? Aún necesitaría una biblioteca real para ello).
un pésimo truco para asociar datos con un objeto de una clase existente, pero crea una pérdida de memoria (OutOfMemoryError) cuando su GC decide tomarse un descanso después de crear sus referencias débiles. Además, es más que feo: un mejor enfoque es usar tuplas.
un pésimo truco para asociar datos con un objeto de una clase existente, donde la clase tiene el descaro de no poder subclasearse, y se usa en un código de función existente al que debe llamar. En tal caso, la solución adecuada es editar la clase y hacer que sea subclase, o editar la función y hacer que tome una interfaz en lugar de una clase, o use una función alternativa.
fuente
equals()
es solo identidad de objeto? Las referencias suaves parecen un desperdicio allí, porque una vez que un objeto clave ya no es fácilmente accesible, nadie volverá a buscar esa asignación nuevamente.Los seis tipos de estados de accesibilidad de objetos en Java:
Para más detalles: https://www.artima.com/insidejvm/ed2/gc16.html «collapse
fuente
Se debe tener en cuenta que un objeto débilmente referenciado solo se recopilará cuando SOLO tenga referencias débiles. Si tiene tanto como una referencia fuerte, no se recopilará sin importar cuántas referencias débiles tenga.
fuente
Para dar un aspecto de uso de memoria en acción, realicé un experimento con referencias Strong, Soft, Weak & Phantom bajo carga pesada con objetos pesados al retenerlos hasta el final del programa. Luego monitoreó el uso del montón y el comportamiento del GC . Estas métricas pueden variar caso por caso, pero seguramente brindan una comprensión de alto nivel. A continuación se encuentran los hallazgos.
Comportamiento de montón y GC bajo carga pesada
Puede obtener gráficos más detallados , estadísticas, observaciones para este experimento aquí .
fuente
WeakReference : los objetos a los que solo se hace referencia débilmente se recopilan en cada ciclo de GC (menor o completo).
SoftReference : cuando los objetos a los que solo se hace una referencia suave se recopilan depende de:
-XX: SoftRefLRUPolicyMSPerMB = N flag (el valor predeterminado es 1000, también conocido como 1 segundo)
Cantidad de memoria libre en el montón.
Ejemplo:
Luego, el objeto al que hace referencia SoftReference solo se recopilará si la última vez que se accedió es mayor de 10 segundos.
fuente