studio - Prueba una referencia débil antes de usarla java
android studio weakreference (1)
En un proyecto de Android multiproceso, veo un código como este:
final WeakReference<MyClass> myClassObjectWeakRef =
new WeakReference<MyClass>(aMyClassObject);
... luego en otro lugar:
if (myClassObjectWeakRef.get() != null) {
myClassObjectWeakRef.get().someMethod();
}
Estoy bastante seguro de que existe una posible condición de carrera entre la verificación y el uso de la referencia, si la última referencia segura al objeto se libera entre los dos en otro hilo, pero no puedo encontrar ninguna documentación o cualquier persona que / ¿Quién puede confirmar esto mejor que con un "tienes razón probablemente".
Creo que la única forma correcta de probar y usar una referencia débil se hace así:
MyClass myObject = myClassObjectWeakRef.get();
// we now have a strong reference, or null: standard checks apply.
if (myObject != null) {
myObject.someMethod();
}
Estoy seguro de que el segundo método es 100% seguro, pero me pregunto si hay algo de Java / compiler sugar / magic que no conozco, lo que haría que el primer método sea seguro.
Entonces, ¿es el primer método 100% seguro, o no?
El primer método es definitivamente inseguro. Cada llamada a get
es independiente. No hay nada que evite que el GC despeje el objeto débilmente accesible después de la primera get
y antes de la segunda.
Los estados javadoc
Supongamos que el recolector de basura determina en un determinado momento que un objeto no es fácilmente accesible. En ese momento, eliminará atómicamente todas las referencias débiles a ese objeto y todas las referencias débiles a cualquier otro objeto de difícil acceso desde el cual se pueda acceder a ese objeto a través de una cadena de referencias fuertes y suaves.
Eso puede ser en cualquier momento en el tiempo. Al llamar a get()
, que (potencialmente) inserta una referencia al objeto en la pila, hace que el objeto sea fácilmente accesible (está en la pila de un hilo), pero esa capacidad de alcance desaparece en el momento en que finaliza la comparación con null
. Después de ese momento, el GC puede determinar que el objeto es débilmente accesible y borrar su referencia. Entonces obtendrías una NullPointerException
.
Usa tu segundo método. Pero tenga en cuenta que al asignarlo a una variable, está haciendo que el objeto al que se hace referencia sea muy accesible.