Referencias débiles en Java

1. Información general

En este artículo, veremos el concepto de referencia débil, en el lenguaje Java.

Vamos a explicar qué son, para qué se utilizan y cómo trabajar con ellos correctamente.

2. Referencias débiles

El recolector de basura borra un objeto con referencias débiles cuando no se puede acceder a él.

La accesibilidad débil significa que un objeto no tiene referencias fuertes ni suaves que lo apunten . Solo se puede llegar al objeto atravesando una referencia débil.

En primer lugar, Garbage Collector borra una referencia débil, por lo que el referente ya no es accesible. Luego, la referencia se coloca en una cola de referencias (si existe alguna asociada) de donde podemos obtenerla.

Al mismo tiempo, se finalizarán los objetos que antes eran poco accesibles.

2.1. Referencias débiles vs suaves

A veces, la diferencia entre referencias débiles y blandas no está clara. Las referencias blandas son básicamente una gran caché LRU. Es decir, usamos referencias blandas cuando el referente tiene buenas posibilidades de ser reutilizado en un futuro próximo .

Dado que una referencia suave actúa como un caché, puede seguir estando accesible incluso si el referente en sí no lo es. De hecho, una referencia blanda es elegible para la recopilación si y solo si:

  • El referente no es muy accesible
  • No se ha accedido recientemente a la referencia suave

Por lo tanto, una referencia suave puede estar disponible durante minutos o incluso horas después de que el referente se vuelva inalcanzable. Por otro lado, una referencia débil estará disponible solo mientras su referente aún esté presente.

3. Casos de uso

Como se indica en la documentación de Java, las referencias débiles se utilizan con mayor frecuencia para implementar mapeos de canonización . Un mapeo se llama canonicalizado si solo contiene una instancia de un valor particular. En lugar de crear un nuevo objeto, busca el existente en el mapeo y lo usa.

Por supuesto, el uso más conocido de estas referencias es la clase WeakHashMap . Es la implementación de la interfaz Map donde cada clave se almacena como una referencia débil a la clave dada. Cuando el recolector de basura elimina una clave, la entidad asociada a esta clave también se elimina.

Para obtener más información, consulte nuestra guía de WeakHashMap.

Otra área en la que se pueden utilizar es el problema del escucha inactivo .

Un editor (o un tema) tiene fuertes referencias a todos los suscriptores (u oyentes) para notificarles sobre los eventos que sucedieron. El problema surge cuando un oyente no puede darse de baja con éxito de un editor.

Por lo tanto, un oyente no puede ser recolectado como basura, ya que una fuerte referencia a está disponible para un editor. En consecuencia, pueden ocurrir pérdidas de memoria.

La solución al problema puede ser un sujeto que tenga una referencia débil a un observador que permita que el primero sea recolectado como basura sin la necesidad de darse de baja (tenga en cuenta que esta no es una solución completa y presenta algunos otros problemas que no lo son). cubierto aquí).

4. Trabajar con referencias débiles

Las referencias débiles están representadas por la clase java.lang.ref.WeakReference . Podemos inicializarlo pasando un referente como parámetro. Opcionalmente, podemos proporcionar un java.lang.ref.ReferenceQueue :

Object referent = new Object(); ReferenceQueue referenceQueue = new ReferenceQueue(); WeakReference weakReference1 = new WeakReference(referent); WeakReference weakReference2 = new WeakReference(referent, referenceQueue); 

El referente de una referencia se puede recuperar mediante el método get y eliminar manualmente mediante el método clear :

Object referent2 = weakReference1.get(); weakReference1.clear(); 

El patrón para trabajar de forma segura con este tipo de referencias es el mismo que con las referencias suaves:

Object referent3 = weakReference2.get(); if (referent3 != null) { // GC hasn't removed the instance yet } else { // GC has cleared the instance }

5. Conclusión

En este tutorial rápido, echamos un vistazo al concepto de bajo nivel de una referencia débil en Java y nos centramos en los escenarios más comunes para usarlos.