DotNetGuy
DotNetGuy

Reputation: 31

What is root reference?

class GCTest {
     static Object r1; 

     static void Main() {
         r1 = new Object();
         Object r2 = new Object();
         Object r3 = new Object();
         System.GC.Collect(); // what can be reclaimed here ?

         r1 = null;
         r3.ToString();
         System.GC.Collect(); // what can be reclaimed here ?
     }
    }

// code from - DonBox's Essential .Net

Upvotes: 3

Views: 1589

Answers (5)

Andrey Taptunov
Andrey Taptunov

Reputation: 9495

  • object that allocated in Main() and assigned to r1 will be collceted because it's unreachable after r1 set to null.
  • r2 and r3 are local variables in Main() and therefore they are roots in this context.

Upvotes: 0

Thomas Pornin
Thomas Pornin

Reputation: 74382

The GC may collect whichever object for which it can prove that it makes no difference for the application. One way to think about it is the following: objects are allocated forever but the implementation is allowed to reclaim memory as long as it makes sure that you cannot notice it.

In your example, at the first GC.Collect(), the first object reference has been written to r1, and r1 is a static variable, thus somehow "permanent". From the point of view of the GC, just about any code could use that static variable, so the GC cannot make sure that the first object will not be used. Therefore it cannot collect it. The second object, on the other hand, is written in a local variable. The local variable is limited to the method code (it disappear when the method exits) and the GC is able to notice that r2 will not be used anymore (the GC only needs to look at the method, not the whole code, so this is part of what the GC can reasonably do). Therefore, the GC may collect the second object (there is no obligation here).

The third object will still be used after the first GC.Collect(): its ToString() method is called. Hence the GC should not collect it. However, it is conceivable that the VM notices that this is a true Object instance (not any other class), inlines the call to ToString(), and further concludes that the whole ToString() call is an elaborate way of doing nothing (no visible outcome). As such, the GC might be able to collect the third object and skip the call to ToString() altogether.

Of course the GC is free not to collect things as well. The whole point of the GC is that it runs "behind the scene", without impacting the code execution (this is not entirely true in presence of finalization, but that's an extra layer of complexity which should not be envisioned until you master the basics).

Wilson's article is indeed a must-read for anybody wishing to understand what garbage collection does.

Upvotes: 2

Karel Frajták
Karel Frajták

Reputation: 4489

Try your code with WeakReference and you will see, when these references are alive. Try also to go outside your method. GC only reclaims r1. WeakReference can give you better insight, when your references go dead.

The response with exception is of course a nonsense. The only exception that can r3.ToString() rise is null reference exception, but iff r3 is null.

Upvotes: 2

Preet Sangha
Preet Sangha

Reputation: 65506

To me it means the first object in a reference chain. ie A refers to B and B to C etc. A is a Root as nothing else refers to it.

At the first one.

r1 Is static and GC test is holding a reference to it so cannot be collected, while r2 can be collected. r3 will be unless you're in a Debugger or GC.KeepAlive is called

At the second one

r1 can be collected as it no longer in scope r2 is already collected And dependent on whether r3 was collected, it may have raised an exception, or will be collected.

Upvotes: 0

David M
David M

Reputation: 72870

At the first line, there are no further references to r2, so this object could be reclaimed at this point. At the last line, the object created for r1 no longer has a reference, and the local variables r2 and r3 are finished with, so all three objects could be reclaimed at this point. However, this will depend on how it is all compiled.

The three are all root references, as nothing else refers to them. Had r1 been an instance field rather than a static one, then a reference to your GCTest class would have made the r1 reference not a root reference.

Upvotes: 3

Related Questions