¿Cuáles son los beneficios de usar WeakReferences?

Tengo algunas pérdidas de memoria en mi aplicación. Todos se originan en torno a un clúster de vista específico en el que he pasado mucho tiempo retocando y tratando de reducir un paso contextual lo más posible. Esto me lleva a creer que los mapas de bits utilizados en el clúster son el problema. Así que estaba pensando en usar WeakReferences para todas las referencias a los mapas de bits utilizados por las vistas. Nunca he usado una WeakReference y no estoy seguro de si es una buena aplicación. ¿Puede un cuerpo proporcionar consejos o consejos útiles?

Respuesta 1

Así que estaba pensando en usar WeakReferences para todas las referencias a los mapas de bits utilizados por las vistas. Nunca he usado una WeakReference y no estoy seguro de si es una buena aplicación. ¿Puede un cuerpo proporcionar consejos o consejos útiles?

Tenga cuidado, esto es peligroso en su caso. El GC podría deshacerse de todos sus mapas de bits, mientras que su aplicación aún puede necesitarlos.

La cuestión clave sobre WeakReference es comprender la diferencia con referencias duras. Si no hay más referencias duras a un mapa de bits en su aplicación, entonces el GC puede eliminar atómicamente el objeto de la memoria y toda la referencia débil existente apuntará instantáneamente a nulo. En su caso, NO PUEDE usar referencias débiles en todo su código.

Aquí hay una idea de la solución. Cree un objeto contenedor que mantenga referencias débiles (solo) a todos sus mapas de bits. Sus vistas siempre deben hacer referencia a mapas de bits con referencias estrictas solamente. Cuando una vista crea un mapa de bits, debe registrarlo en el objeto contenedor. Cuando quiere usar una vista, debe obtener una referencia sólida del contenedor.

De esta manera, si ninguna vista se refiere a un mapa de bits, entonces el GC recopilará el objeto sin efectos secundarios para las vistas, ya que ninguna tiene una referencia sólida. Cuando se utilizan objetos con referencias débiles, es una buena práctica establecer explícitamente referencias duras en nulo cuando ya no necesite el objeto.

Adición

Aquí hay una implementación rápida de la solución (solo para dar una idea):

public class BitmapContainer {

    public static class Bitmap {
        private final long id;
        public Bitmap(long id) { this.id = id; }
        public long getId() { return id; }
        public void draw() { };
    }

    WeakHashMap<Bitmap, WeakReference<Bitmap>> myBitmaps
        = new WeakHashMap<Bitmap, WeakReference<Bitmap>>();

    public void registerBitMap(Bitmap bm) {

        if ( bm == null ) throw new NullPointerException();

        WeakReference<Bitmap> wr = new WeakReference<Bitmap>(bm);
        myBitmaps.put(bm, wr);

    }

    /** Method returns null if bitmap not available */
    public Bitmap getBitMap(long id) {

        for ( Bitmap item : myBitmaps.keySet() ) {
            if ( item != null) {
                if ( item.getId() == id ) {
                    return item;
                }
            }
        }

        return null;

    }

}
Respuesta: 2

El uso más directo de referencias débiles que se me ocurre es un caché. Desea agregar objetos a un caché, pero si no hay referencias al objeto en el resto de la VM, desea que el objeto obtenga GC'ed sin tener que regresar y eliminarlo del caché usted mismo. Las referencias débiles logran esto. Agrega una referencia débil al objeto en su caché. Cuando el caché es lo único que se refiere a su objeto, es elegible para GC. Los intentos de utilizar la referencia débil después de que el objeto se haya generado por GC resultan en una excepción.

Estrictamente hablando, un objeto es elegible para GC cuando no quedan referencias fuertes a él (es decir, si existen referencias débiles o no).

Según su descripción de su situación, no está claro que las referencias débiles lo ayuden. Pero si se enfrenta a una situación en la que necesita borrar intencionalmente referencias a objetos que ya no se necesitan, entonces las referencias débiles pueden ser la solución. Solo debe asegurarse de que cuando solo queden referencias débiles, realmente esté bien deshacerse del objeto.

Respuesta: 3

La necesidad de WeakReferences proviene de un escenario en el que necesita mantener metadatos sobre un objeto para el que no controla.

Un ejemplo artificial sería String, es final, y no podemos extenderlo, pero si quisiéramos mantener algunos datos adicionales sobre una Stringinstancia específica , probablemente usaríamos una Mapimplementación que contenga estos metadatos. Para este ejemplo, sugeriré que queremos mantener la longitud de la cadena como nuestros metadatos (sí, sé que el Stringobjeto ya tiene una propiedad de longitud pública). Por lo tanto, crearíamos algo Mapasí:

Map<String, Integer> stringLengths = new HashMap<String, Integer>();

Suponga que podríamos poblar este mapa con algún método, y no saber cuándo hemos terminado con los datos, por lo que no podemos eliminar explícitamente las entradas. A medida que poblamos este mapa, que nunca estará despoblado, nuestras referencias se mantendrán para siempre. Si la aplicación se ejecuta durante mucho tiempo, existe una buena posibilidad de que nos encontremos con un OutOfMemoryError.

Una solución a esto sería utilizar una WeakHashMapimplementación.

Map<String, Integer> stringLengths = new WeakHashMap<String, Integer>();

De esta manera, cuando todas las referencias (fuertes) a la clave hayan desaparecido, el próximo GC hará WeakHashMapque se elimine la entrada de la clave . (Sí, entiendo que Stringtiene un lugar especial en el corazón de la JVM, pero supongo que las cadenas tienen GC de la misma manera que un Objeto normal en este ejemplo artificial)

Si este es el enfoque que está utilizando en su aplicación (almacenando sus mapas de bits en un mapa global), creo que esto es definitivamente algo a tener en cuenta.

Respuesta: 4

Estoy usando Selenium WebDriver (ChromeDriver). Necesito eliminar algunos elementos de la página después del procesamiento (del modelo DOM). Por ejemplo, tengo un elemento siguiente: WebElement starRatingElement = ...

Estoy tratando de crear una biblioteca de medición de rendimiento personalizada, que un usuario puede usar para medir el rendimiento de cualquier método en una aplicación. Mi objetivo es lograr esto sin cambiar el ...

Tengo una carpeta llamada salida dentro de un cubo llamado BucketA. Tengo una lista de archivos en la carpeta de salida. ¿Cómo los descargo a mi máquina local con AWS Java SDK? A continuación se muestra mi código: AmazonS3Client ...

Estoy en duda con eso, en lenguaje Java, necesitamos adquirir el bloqueo, antes de esperar alguna condición para ser satisfecho. Por ejemplo, bloqueo de monitor int java: sincronizado (bloqueo) {System.out.println (...