Last sunday we had a session on .NET Internals as part of the monthly session of Kolkata .NET User group.The session went very well.But the discussion on what exactly happens for GC of a WeakReference class remained open ended.After going through Jeffrey Richters book “CLR via C#” I found lot of information on how the WeakReference class works.
For every app domain CLR maintains a table called GC Handle table.This table can be accessed via the System.Runtime.InteropServices.GCHandle class.Along with GCHandle there is an enumeration called GCHandleType which needs to be passed to the Alloc method of GCHandle class
The four values of this enumeration are:
1)Weak – This handle type is used to track an object, but allow it to be collected. When an object is collected, the contents of the GCHandle are zeroed. Weak references are zeroed before the finalizer runs.
2)WeakTrackResurrection-This handle type is similar to Weak, but the handle is not zeroed if the object is resurrected during finalization.
3)Normal-This handle type is used to track an object and prevent its collection by the garbage collector. This enumeration member is useful when an unmanaged client holds the only reference, which is undetectable from the garbage collector, to a managed object.
4)Pinned-This handle type is similar to Normal, but allows the address of the pinned object to be taken. This prevents the garbage collector from moving the object i.e. perform compaction.
WeakReference class is wrapper around GCHandle class with the GCHandleType – Weak and WeakTrackResurrection.WeakReference constructor calls to GCHandle’s Alloc method and Target is same as the Target property of GCHandle class.
One of the overloaded constructor of this class is WeakReference(Object, Boolean).The boolean parameter if false then it is called a short weak reference otherwise a long weak reference.By default it is always short weak reference.
Short Weak Reference
The target of a short weak reference becomes null when the object is reclaimed by garbage collection.(Weak)
Long Weak Reference
A long weak reference is retained after the object’s Finalize method has been called. This allows the object to be recreated, but the state of the object remains unpredictable.(WeakTrackResurrection)
The GC in the marking phase also scans this GC Handle table to identify the object is reachable/unreachable.
As per MSDN Guidelines for Using Weak References are
Use long weak references only when necessary as the state of the object is unpredictable after finalization.
Avoid using weak references to small objects because the pointer itself may be as large or larger.
Avoid using weak references as an automatic solution to memory management problems. Instead, develop an effective caching policy for handling your application’s objects.
I found a very good suggesstion in Jeffrey Richters book in this regard.GC does not occur when the memory is full but occurs when the Generation 0 becomes full which is after 256 KB of memory allocation.So using WeakReference might lead to collection & re-creation of a memory intensive object even when there is no memory crunch.This can result in significant performance hit.So while using WeakReference for caching scenario we have to strike a balance between memory usage and appliaction performance.The caching algorithm needs to be designed with care and adhoc usage of WeakReference will not solve the problem.