How to handle a memory leak in an external DLL
I have an external (.Net) dll that I have to use for an application. Unfortunately that dll has several known memory leaks. We are working on getting the authors of the dll to fix the memory leaks, but in the mean time I was wondering what is the best way to use the开发者_如何学JAVA dll without having to deal with the memory leaks?
Moving the .Net assembly into its own AppDomain so you can unload the module periodically may help if the leaks are due to hanging onto object references "too long", but most "memory leak" situations I've run into in .Net managed code are actually failure to release unmanaged resource handles - releasing handles, closing files, closing network connections, etc.
If the resources are owned by a responsible .Net managed object that releases its unmanaged handles in IDispose.Close(), but some bonehead code isn't calling IDispose.Close when it's supposed to, forcing a GC cycle or unloading the assembly's AppDomain may help reclaim those orphaned unmanaged resources by "hurrying up" the eventual GC disposal of the owning managed objects.
If the handles are owned by bonehead code that doesn't release them properly at all, unloading the assembly's AppDomain is unlikely to help reclaim the orphaned handles.
Most Windows resources associated with handles will be recovered when the process terminates. This is a bit extreme, but if GC and AppDomain cycling don't help, you could write a wrapper around the offending .NET assembly classes and use .NET remoting to jettison the offending assembly from your process entirely. How much data interaction goes on between the offending assembly's classes and the rest of your app will determine whether this is at all feasible. If the offending assembly is fairly self-contained with a smallish number of interfaces entry points, this could be doable. With the offending assembly in its own process, you could shut it down periodically to purge the accumulated cruft, without having to shut down your own process.
Definitely hold that last idea for the absolute last resort. Try to find out what kind of memory or resource is being leaked and how it's being leaked and whether AppDomain cycling will reclaim the lost resources.
Unless it's been obfuscated, use .NET Reflector and take the code out, find the relevant part, fix it, recompile it, and use the recompiled code.
This may or may not work for your environment. Works for me when I have to figure out how to interface with some vendors stuff if they REFUSE me documentation. But bear in mind your business may have an issue with you using .NET Reflector.
I don't know if this is necessarily applicable to .NET, but can you unload the DLL, and reconnect it? This should cause a de-allocation of used memory (including leaked), and then you reload the library and head back on your merry way. Finding a time to unload the DLL could obviously be tricky. ;)
Relevant links appear to be:
- http://msdn.microsoft.com/en-us/library/ms173101%28VS.80%29.aspx
- http://www.codeproject.com/KB/cs/DotNet.aspx
We had a service that uses a third party library (developed in Java), and we believe that there is a memory leak with this library. We decided that the easy way to deal with the problem was to separate the service in two different modules, one that is the service itself and the other one which contains the business code, and which is an executable file. So the service loops, calls the other executable, which runs in its own memory space, and then finishes its execution, never poluting the service application with its memory leak.
So my suggestion is to isolate your program from the faulty DLL, either by shortening the time you work with it, or changing the architecture of your system so you don't deal with this DLL directly from the "long running" application.
If it's a serious issue, load the assembly into a seperate AppDomain and create instances of your dodgy classes in isolation. It also provides a nice security boundary.
If there are static members holding onto variables, there is nothing you can do about the leak in your current appdomain, so using another one is a great way to provide component isolation.
Once a assembly is loaded into a IAppDomain, it cannot be unloaded, but the entire AppDomain can be torn down and the GC will collect it.
精彩评论