GC Handle Identification
GC handles are used to create handles to managed instances. They act as roots for the garbage collector and can be used to prevent an instance from being collected, to pin a managed instance in memory, or to create a weak reference to an instance. The .NET Framework provides access to GC handles through the System.WeakReference
class and the System.InteropServices.GCHandle
structure. The runtime also uses GC handles internally to keep track of certain instances, such as managed COM interfaces and static field data.
.NET Memory Profiler can identify the internal GC handles that are created by the runtime itself or by using the WeakReference and GCHandle types. If GC handle identification is enabled (using Preferences in the Options dialog), a pseudo-Type called <GCHandle> will be presented by the profiler. This type represents the internal GC handles used by the runtime; it does not map to a real managed type. The <GCHandle> type and its instances can be investigated in the same way as any other managed type, e.g., by viewing the details of the type or the instances.
Root Kind
A GC handle acts as a root for the garbage collector, and, depending on the kind of root, it will affect the garbage collector in different ways. Below is a list of root kinds and descriptions of how they affect the garbage collector.
Weak
A weak GC handle will not prevent the instance it corresponds to from being garbage collected. Weak GC handles are, for instance, used by theSystem.WeakReference
class.Pinned
A pinned GC handle prevents the corresponding instance from being garbage collected and from being moved in memory.Normal
A normal GC handle prevents the corresponding instance from being garbage collected.RefCounted
A reference counted GC handle is used internally by the runtime, e.g., when dealing with COM interfaces.
GCHandle Root Identification
Normally a <GCHandle> root is not considered to be “identified” when calculating root paths in the Type details and Instance details view. That is, a root path ending in a <GCHandle> will not be presented if the Only include identified roots option is enabled.
However, if the Treat System.InteropServices.GCHandles roots as identified option is enabled in the Preferences screen and the runtime <GCHandle> is stored in a GCHandle structure field (or a boxed GCHandle instance), it will be treated like an identified root.
Note
This can considerably affect the way the root paths are presented for some types and instances. For example, a top level System.Windows.Forms.Form is kept alive using a <GCHandle> allocated using GCHandle.Alloc
. If GCHandle roots are treated as identified, the first root path will be a direct root to the top-level form, as can be seen in the picture below.
If GCHandle roots are not treated as identified, the direct root will not be included, as can be seen in the picture below.
<GCHandle> Type Details
The type details of the <GCHandle> pseudo-type include the same information as for any other type, with two differences.
The Instances list contains one additional column (Root kind) that provides information about the kind of root.
The Size (with children) column is not available in the Instances list.
<GCHandle> Type Instance Details
The type instance details of a <GCHandle> instance include the same information as any other instance. Additionally, the root kind of the GC handle is included in the info panel at the top.
WeakReference and GCHandle Presentation
The implementation of WeakReferences and the managed GCHandle structure makes use of the runtime GC handles, and this is reflected in the presentation of instance details of these types.
If GC handle identification is enabled, the References list in the Type instance details view will include a reference to the <GCHandle> instance, as shown below.
If GC handle identification is not enabled, the list will include a direct reference to the target of the GC handle, as shown below.