Overview
The content of this post was written in response to a query by a colleague wanting to reclaim memory used by a .NET component used as part of a legacy application. Concerns were also raised about memory leaks in .NET. In this post I describe some of the basics of .NET and COM memory management, and how to explicitly manage .NET component memory use.
Reference counting
To understand memory management in .NET versus in COM, you first need to understand reference counting.
In a COM application, each time an object is accessed the client informs the object that it is using another reference. Later, the client informs the object that a reference is no longer needed. When the number of references reaches zero, the object lifetime is ended.
.NET uses an automatic method of managing reference counts based on a garbage-collection methodology. The object lifetime is considered to have ended in two cases. In the first case, the Dispose method (part of the IDisposable interface) is called on the object. In the second case, no other (active) objects have a reference to the object.
Memory management in COM
When a COM object lifetime has ended, the COM object is responsible for releasing all memory associated with it. Since this occurs precisely when all references have been released, the COM object lifetime is explicitly managed and so is its memory lifetime. However, a badly written COM object can fail to release all memory and this is known as a memory leak, i.e. memory is allocated that is not referenced by anything that is actually still running.
Memory management in .NET
.NET uses a garbage collection approach, similar to Java. In .NET, the runtime is responsible for memory management. The memory lifecycle is not tied to object lifetime. Instead, the garbage collector periodically reclaims memory. However, because this is the .NET runtime reclaiming memory, that memory is not necessarily released back to the system. When the process ends, all memory used in that process is returned to the system without memory leaks, something that the system does not guarantee for a COM object (it is the responsibility of a COM object to do this).
The .NET garbage collector monitors overall system memory usage and tunes garbage collection events accordingly.
Explicitly managing memory allocation in .NET
You can use methods of the System.GC class to cause .NET to perform a garbage collection. This class is also supported by the System.Runtime namespace.
If you really need to ensure that the component releases all memory then you need to shutdown the process after the request has completed. This is best achieved by using COM+ activation features. You can perform administrative management of COM+ using Component Services however you also need to design-in support. Note that Component Services is not related to COM objects that do not also use either COM+ or DCOM services.
To do this, you should use COM+ and you should not use Object Pooling. You must also configure your COM+ component in a dedicated server application. This type of COM+ application guarantees that the object runs in a dedicated process which ensures that the memory is released when the object is no longer needed. You should also configure application recycling so that the application restarts regularly.
If you need to access this component from another machine then you should export a COM+ proxy to that machine. This can be accomplished using the Component Services management tool.
References
Have a look at the following for more information:
Versions
- Microsoft .NET Framework 2.0
Metadata
- Categories: .NET, COM, COM+, Software Development, Memory Management
- Additional keywords: object pooling, garbage collection, proxy, marshalling, interoperability
- Technorati Tags: .NET, software development, DCOM, COM+, memory management, marshalling, integration, garbage collection