Analyze GC Roots

Last modified: 17 June 2024

The retention path of an object always starts with a GC root. From the point of the Garbage Collector, the root is a reference to an object that must not and will not be collected. This makes roots the only possible starting point for building retention graphs. Understanding root types can be essential during the "Who retains the object?" analysis. Sometimes examining retention paths doesn't answer why the object is still in memory. In this case, it makes sense to look at GC roots. For example, a RefCounted handle indicates that some unmanaged COM library retains the object.

There are four possible root types in .NET Framework:

  • Stack references: references to local objects. Such roots live during method execution.

  • Static references: references to static objects. These roots live the entire app domain lifetime.

  • Handles: typically, these are references used for communication between managed and unmanaged code. Such roots must live at least until the unmanaged code needs "managed" objects.

  • Finalizer references: references to objects waiting to be finalized. These roots live until the finalizer is run.

To analyze a root of a retention path, use the Shortest Paths to Roots view that shows object retention paths. Note that all root types distinguished by dotMemory fall into one of the categories mentioned in the list above.