public class MyClass {
private static MyClass heldInstance;
public MyClass() {
heldInstance = this;
}
}
Assuming an instance of MyClass is not rooted in any other way, will the private static reference here prevent it from being garbage collected?
Since there's effectively always a "reference" to the static object, it will never get garbage collected.
Because static variables are referenced by the Class objects which are referenced by ClassLoaders. So, Static variables are only garbage collected when the class loader which has loaded the class in which static field is there is garbage collected in java.
The . NET garbage collector can absolutely handle circular references.
The class you posted will not be garbage collected. You can test this by giving it a finalizer with a console output:
public class MyClass
{
private static MyClass heldInstance;
public MyClass()
{
heldInstance = this;
}
~MyClass()
{
Console.WriteLine("Finalizer called");
}
}
class Program
{
static void Main(string[] args)
{
var x = new MyClass(); // object created
x = null; // object may be eliglible for garbage collection now
// theoretically, a GC could happen here, but probably not, with this little memory used
System.Threading.Thread.Sleep(5000);
// so we force a GC. Now all eligible objects will definitely be collected
GC.Collect(2,GCCollectionMode.Forced);
//however their finalizers will execute in a separate thread, so we wait for them to finish
GC.WaitForPendingFinalizers();
System.Threading.Thread.Sleep(5000);
Console.WriteLine("END");
}
}
The output will be:
END
Finalizer called
Which means that the class only gets collected at the final teardown of the application, not during a regular garbage collection.
If you create multiple instances of this class like this:
var x = new MyClass();
x = new MyClass();
x = new MyClass();
x = new MyClass();
then all except the most recent one will be garbage collected.
You would get
Finalizer called
Finalizer called
Finalizer called
END
Finalizer called
The garbage collector determines which objects are reachable and will collect those that are not. To determine whether an object is reachable, the collector will start with the so called roots. Among the roots are the things currently on the evaluation stack, but also static fields. The collector will follow the references to objects from the roots to any object, and from such an object to any other object, and so on. Each object that has been visited this way is reachable and will therefore be kept alive.
In your case the static field is one of the garbage collector's roots, and therefore it will never collect any object that is referenced (indirectly) by that field. However, if you set the field to null
then that field no longer references the instance and the instance may be collected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With