Considere estas dos clases:colector de basura y la referencia circular
public class A
{
B b;
public A(B b) { this.b = b; }
}
public class B
{
A a;
public B() { this.a = new A(this); }
}
Si he clases diseñada como la de arriba, serían los objetos de dichas clases serán recogidos por recolector de basura (GC)?
Supongamos que hago esto:
void f()
{
B b = new B();
}
En este método, se crea una instancia de B
llamada b
, y cuando el método retorna, b
sale del ámbito y el GC debería ser capaz de recogerlo , pero si se tratara de recopilarlo, primero tendría que recopilar a
, que es el miembro de B
, y para recopilar a
, primero debe recopilar b
, que es el miembro de A
. Se vuelve circular. Entonces mi pregunta es: ¿tal referencia circular va a evitar que GC recolecte los objetos?
- En caso afirmativo, ¿cómo podemos evitar este problema? ¿Cómo podemos asegurarnos de que no tengamos referencias circulares en nuestro diseño de clase? ¿Hay alguna herramienta (o opción de compilación) que nos ayude a detectar referencias circulares?
- En caso negativo, ¿dónde y por qué usamos la clase
WeakReference
? ¿Cual es su propósito?
Eche un vistazo aquí http://stackoverflow.com/questions/400706/circular-references-cause-memory-leak –
Al menos lógicamente una de las referencias siempre será débil: en su ejemplo, cleary 'A 'no puede depender de' B', porque 'A' debe hacerse primero, como miembro de' B', y 'A' solo puede contener una referencia débil a' B'. Por lo tanto, es seguro destruir 'B' primero y luego' A'. Argumentando recursivamente, cada programa de computadora debe ser así. Nunca puede haber una dependencia circular * verdadera *, totalmente simétrica. –
@KerrekSB: Estoy de acuerdo con esa lógica. Pero eso se ve desde el punto de la creación. ¿El GC va a analizar esto (es decir, el código en cada método de tales clases, después de todo, solo entonces puede llegar a esa conclusión)? Quiero decir, si ves los objetos después de que han sido creados, entonces parece muy problemático. – Nawaz