The Microsoft .NET Framework provides an automated mechanism for reclaiming an object that is no longer in use. This process is usually referred as Garbage Collection. I strongly believe that a clear understanding of this mechanism is required for developing a resource-extensive application, especially if resources are unmanaged. This article gives you an overview of how CLR performs Garbage Collection, as well as highlights various options and best practices available in .NET 2.0 and .NET 3.0.
CLR and Garbage Collection
The Microsoft .NET Framework CLR reserves space for each object instantiated in the system. Since memory is not infinite, CLR needs to get rid of those objects that are no longer in use so that the space can be used for other objects. The very first step in Garbage Collection is identifying those objects that can be wiped out. To accomplish this step, CLR maintains the list of references for an object. If an object has no more references, i.e. there is no way that the object could be referred to by the application, CLR considers that object as garbage. During Garbage Collection, CLR reclaims memory for all garbage objects.
For details about the algorithm CLR uses to maintain the list of references for an object and consider an object as garbage, please read the article Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework by Jeffrey Richer.
CLR could clean all the managed resources, but have absolutely no knowledge of how to clean an unmanaged resource. Thus, if your object had an internal unmanaged resource, CLR could not reclaim it. For this purpose, .NET provides you a feature of Finalization. Finalization allows a managed resource to gracefully clean all its unmanaged resources before it is reclaimed by CLR. Thus, before reclaiming a garbage, CLR calls its
Finalize method (if it exists).
Public class MyClass
Protected void Finalize()
This feature seems to be quite simple and straightforward, but you ought to be very careful while using it for the following reasons:
- You should not access any managed resource in the
Finalize method, as it might already have been reclaimed by CLR. You never know in which order CLR reclaims objects.
- Forcing the garbage collector to execute the
Finalize method before reclaiming could hurt the performance of your application.
- You have no control over when
Finalize will be called.
The garbage collector is exposed in the static
System.GC class. You can force Garbage Collection to run and let it identify the garbage objects, calling its finalization by calling
GC.Collect. However, calling the
GC.Collect method is usually not considered a recommended approach, as it could hurt the performance of your application.
You should also remember that GC runs on its own thread. When GC starts reclaiming garbage, all other threads are stopped. Thus, if you need to release an unmanaged resource immediately after it is no longer required by the system -- or if you want to clean the resources by using a specific thread, e.g. you have stored some data in a thread stack -- you should implement the Dispose pattern. For details about how to implement the Dispose pattern, please read article Implementing a Dispose Method.
Sometimes we deal with managed objects that use a lot of memory, but can be recreated easily. To maximize the performance, we don't want to maintain such objects if the user is not interacting with them. .NET 2.0 introduces a feature called Weak Reference. A weak reference permits the garbage collector to collect the object while still allowing the application to access the object. A weak reference is valid only during the indeterminate amount of time until the object is collected, when no strong references exist. When you use a weak reference, the application can still obtain a strong reference to the object, which prevents it from being collected.
However, there is always the risk that the garbage collector will get to the object first before a strong reference is reestablished. To establish a weak reference with an object, you create a
WeakReference using the instance of the object to be tracked. You then set the
Target property to that object and set the object to null. For a code example, see
WeakReference in the class library. You can create a short weak reference or a long weak reference:
- Short Weak Reference: The target of a short weak reference becomes null when the object is reclaimed by Garbage Collection. The weak reference is itself a managed object and is subject to Garbage Collection just like any other managed object. A short weak reference is the default constructor for
- 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. To use a long reference, specify true in the
If the object's type does not have a
Finalize method, the short weak reference functionality applies and the weak reference is valid only until the target is collected, which can occur any time after the Finalizer is run. To establish a strong reference and use the object again, cast the
Target property of a
WeakReference to the type of the object. If the
Target property returns null, the object was collected; otherwise, you can continue to use the object because the application has regained a strong reference to it.
Events are also considered as strong references and can therefore contribute to the lifetime of an object. Ordinary events in the common language runtime (CLR) 2.0 are bidirectional strong references between the event source and the listener. As such, they can keep an object (either source or listener) alive that otherwise should be dead already. This is why a
WeakEvent class was added in .NET Framework 3.0. It is important that you become familiar with the
WeakEvent pattern, which is not yet well known, but is required to implement the
Observer pattern successfully. The
WeakEvent pattern has been used in the Windows® Presentation Foundation (WPF) Data Binding implementation to prevent leakage due to data binding.
In this article, I tried to present an overview of Garbage Collection. I also highlighted new features of Garbage Collection introduced in .NET 2.0 and 3.0. I hope it will help you in writing a better software.
- 25 October, 2007 -- Original version posted