Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a class that references itself in a static field be garbage collected?

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?

like image 597
Jeff Stewart Avatar asked Feb 26 '13 21:02

Jeff Stewart


People also ask

Do static classes get garbage collected?

Since there's effectively always a "reference" to the static object, it will never get garbage collected.

Why static variables are not 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.

Can garbage collector release isolate circular references?

The . NET garbage collector can absolutely handle circular references.


2 Answers

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
like image 92
HugoRune Avatar answered Sep 20 '22 16:09

HugoRune


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.

like image 23
Daniel A.A. Pelsmaeker Avatar answered Sep 20 '22 16:09

Daniel A.A. Pelsmaeker