En primer lugar, quiero hacerle saber que esta es una pregunta más teórica que práctica, solo tengo curiosidad por saber cómo se desasignan los objetos referenciados débilmente.
Recordemos rápidamente qué es una referencia débil en Java. En términos generales, WeakReference significa desasignar "yo" en cualquier momento que desee cuando no haya referencias fuertes que apunten a "yo" hasta que ese "yo" permanezca vivo. Además, sabemos que hay muchos recolectores de basura diferentes que utilizan diferentes técnicas de recolección. Por ejemplo, en el pasado, Android se basaba en Dalvik GC, que detenía el mundo, lo que literalmente significa que la aplicación se suspendía durante la limpieza de la memoria. Más tarde, Dalvik fue reemplazado por ART, una nueva versión de GC escrita por Google, que es mucho más rápida ya que es concurrente. Entonces, ahora viene mi pregunta: supongamos que tenemos un objeto al que se hace una referencia débil desde algún punto del código y no hay referencias fuertes a este objeto, esto significa que podemos acceder y usar este objeto como de costumbre hasta que el coleccionista no decida. para recuperar su espacio. Entonces, ¿qué sucederá si el recopilador intenta desasignar la memoria retenida por este objeto débilmente referenciado exactamente durante el acceso a través WeakReference ? Me refiero a que el código llama al método get() de la clase WeakRefernce "exactamente" al mismo tiempo que los recopiladores deciden liberar su memoria. En teoría, es posible con los dos tipos de técnicas de GC que describí anteriormente. Dado que Stop-the-world GC suspende la aplicación, ¡la aplicación puede suspenderse "exactamente" cuando accede a este objeto! Para los GC simultáneos, es aún más fácil: el GC ocurre simultáneamente con la ejecución de la aplicación.
Nuevamente, esta es una pregunta teórica, ¡no estoy 100% seguro de que sea posible! Solo trato de entender un caso tan extremo del mundo de Java.
Gracias !
Saludos,
andré
No es tan fácil. Para mantener la coherencia del montón: no accede al montón directamente (al menos cuando GC está activo), accede a él a través de alguna indirección que crea un GC típico. Puede pensar en ello como un "proxy", en el mundo de GC; estas se denominan barriers . aquí hay un ejemplo de cómo lo hace cierto HotSpot Collector, o tal vez quiera leer esto también .
En palabras muy, muy simplificadas, "exactamente durante el acceso", no es exactamente . Será una operación CAS atómica para un ciclo concurrente , pero si es un ciclo que detiene el mundo, las cosas son mucho más triviales. Por lo tanto, nunca puede acceder a una WeakReference::get al mismo tiempo que un GC actúa sobre ella. Si pudiera y un GC lo permitiera, la consistencia del montón desaparecería y también cualquier garantía de que su código funcione.
Mi último punto es que, a menos que Google haya inventado (y patentado un algoritmo para procesar WeakReferences al mismo tiempo), WeakReferences (y Soft/Phantom/Finalizer ) se procesan en una pausa completa.