.NET Garbage Collection Primer

GC Process Revisited

 Managed Object Lifetime
  1. Object constructed on the heap, referenced from the stack
  2. If the object is long lived, it may survive a GC or more and have its Generation promoted.
  3. Object goes out of scope, off the stack
  4. GC runs at some time on the objects Generation and determines that the object is no longer referenced by an application root, so the object is removed from the heap and the memory is reclaimed.
 Unmanaged Finalizable Object Lifetime
  1. Object constructed on the heap, referenced from the stack and the Finalization Queue
  2. If the object is long lived, it may survive a GC or more and have its Generation promoted.
  3. Object goes out of scope, off the stack
  4. GC runs at some time on the objects Generation and determines that the object is still referenced by an application root (the Finalization Queue), so the out-of-scope object has its Generation promoted. The GC also determines that the object is no longer on the stack and is ready for its Finalizer to run, so it moves the reference from the Finalization Queue to the fReachable Queue.
  5. If the GC runs again while the object is still on the fReachable Queue, it will again have its Generation promoted.
  6. At some time the finalization thread will run and the objects Finalizer will be called. The reference to it is then removed from the fReachable Queue.
  7. GC runs at some time on the objects Generation, determines that the object is no longer referenced by an application root, so the object is removed from the heap and the memory is reclaimed.

Potential Problems

The process for unmanaged objects ensures that all finalization code is run (and run separately from the GC) before an object is removed from the heap. The problem is that it might be quite a while between the object no longer being needed and its finalizer being called, during which time it may be holding on to expensive or limited resources. (Remember that an out-of-scope Gen 1 object will be promoted and have to wait until a Gen 2 GC before its finalizer is called). It is even longer until the object is actually removed from the heap.

This looks like a job for IDisposable – see my next post for more details.

References

I would highly recommend anyone interested to read Under the Hood of .NET Memory Management by Chris Farrell and Nick Harrison It is also available as a free PDF.