Referencias circulares en Java


Answers

El recolector de basura sabe dónde están los objetos raíz: estáticos, locales en la pila, etc. y si los objetos no son accesibles desde una raíz, entonces serán recuperados. Si son alcanzables, entonces necesitan quedarse.

Question

Dada una agregación de instancias de clase que se refieren entre sí de forma compleja, circular: ¿es posible que el recolector de basura no pueda liberar estos objetos?

Recuerdo vagamente que esto era un problema en la JVM en el pasado, pero pensé que esto se había resuelto hace años. sin embargo, alguna investigación en jhat ha revelado que una referencia circular es la razón de una fuga de memoria que ahora enfrento.

Nota: Siempre he tenido la impresión de que la JVM era capaz de resolver referencias circulares y liberar esas "islas de basura" de la memoria. Sin embargo, estoy planteando esta pregunta solo para ver si alguien ha encontrado alguna excepción.




El recolector de basura es una pieza de software muy sofisticada; ha sido probado en un enorme banco de pruebas JCK. NO es perfecto PERO hay una posibilidad muy buena de que mientras el compilador de java (javac) compile todas tus clases y JVM lo instanciará, entonces deberías estar bien.

Por otra parte, si mantiene referencias a la raíz de este gráfico de objetos, la memoria NO se liberará PERO si sabe lo que está haciendo, debería estar bien.




La especificación de Java dice que el recolector de basura puede recoger su objeto SOLAMENTE si no se puede acceder desde ningún hilo.

Alcanzable significa que hay una referencia o cadena de referencias que conduce de A a B, y puede ir a través de C, D, ... Z para todo lo que le interesa.

La JVM no recopiló cosas no ha sido un problema para mí desde el año 2000, pero su kilometraje puede variar.

Sugerencia: la serialización de Java almacena en caché los objetos para que la transferencia de malla de objeto sea eficiente. Si tiene muchos objetos grandes y transitorios, y toda su memoria está siendo trabada, reinicie su serializador para borrar su caché.




El recuento de referencias Los GC son notorios para este problema. En particular, Suns JVM no utiliza un GC de recuento de referencias.

Si no se puede acceder al objeto desde la raíz del montón (generalmente, como mínimo, a través de los cargadores de clases si no hay nada más0), los objetos se destruirán ya que no se copiarán durante un GC de Java típico al nuevo montón.




Si recuerdo correctamente, entonces, de acuerdo con las especificaciones, solo hay garantías sobre lo que la JVM no puede recopilar (todo lo que se puede alcanzar), no sobre lo que recolectará.

A menos que trabaje con JVM en tiempo real, la mayoría de los recolectores de basura modernos deberían poder manejar estructuras de referencia complejas e identificar "subgrafos" que puedan eliminarse de manera segura. La eficacia, la latencia y la probabilidad de hacerlo mejoran con el tiempo a medida que más ideas de investigación se abren paso en VM estándar (en lugar de investigación).




Links