All,
I am creating a component that uses composite pattern. The core component uses an XMl Meta data to define the composites (parts). at run time, the core component would use reflection to load the part assembly into the memory and call methods (e.g IPart.execute method).
Now my question is
1) will the (dynamic) memory that is occupied by the assembly that is loaded using reflection will be unloaded when i dispose the object or not.
2) if it does not unload and free the memory, is there is any way i can remove it from memory.
The reason of this question is, the component which i am building will be the core of my Business layer of an enterprise application which can be customized heavily.
Thanks
Albert Arul Prakash
I've seen people load additional libraries via reflection (we could call these libraries "plugins") in another appdomain. For instance, see this article: http://adrianvintu.com/blogengine/post/Unloadable-plugins.aspx
This way you are protected from "evil" plugins as well as memory can be managed in such appdomain (when the appdomain unloads, the memory is freed up as well)
There are two things that can consume memory in a plugin/module. Grossly speaking, these are code (loading the assembly into your process space consumes memory), and objects (creating an instance of something consumes memory).
will the (dynamic) memory that is occupied by the assembly that is loaded using reflection will be unloaded when i dispose the object or not.
Calling Dispose on IDisposable doesn't do anything to the object as far as memory is concerned. It might free resources that the object uses (e.g. if you close a file, it will get rid of open file handles), but it won't free the object itself. IDisposable isn't a magic memory-freeing function - it is just a method on an interface that lets an object know that it should get rid of resources that it owns.
To free the object itself, you must get rid of all references to it (possibly set them to null, or let them fall off your program's stack), and the garbage collector must eventually run to reclaim that memory.
if it does not unload and free the memory, is there is any way i can remove it from memory.
If you are only concerned about resources like GUI and file handles, make sure you call Dispose. You should always do this :)
If you are concerned about object memory, just let the GC do its work. Don't pester it to, either. Let it run on its own.
If you are concerned about code memory, you must unload the AppDomain that the code is in. If this is your default AppDomain then you can't unload it without quitting your program. Instead, you should load that plugin in a sub AppDomain that you created at runtime. You can then get the code out of your process space by unloading the sub AppDomain.
See naivists' answer for information on how to use a sub AppDomain.
Related
I noticed in testing, that multiple calls to the following code creates a memory leak :
object obj = Activator.CreateInstance(Type.GetType(arg2.DeclaringType.FullName));
arg2.Invoke(obj, new object[] { arg3 });
For the above code, arg2 is MethodInfo type ; arg3 is string[]
Even if I add obj = null; after the Invoke, it seems that GAC doesn't collect this object for cleanup. (yes, I know setting an object to null is a poor excuse for dispose(), however as this is a generic method, there may or may not be a dispose() available in the class, and tested with assemblies that do have dispose, they are not unloaded after use)
I have consider using a cache mechanism where the loaded assembly is stored in a dictionary for subsequent lookups, however there is no guarantee that GAC won't come and clean it up later making that object in dictionary unusable (among other disasters).
How can I force an unload of the class (similar to the way I can force it to load by calling Activate) once I am finished with it ?
Let's get this straight, you can not unload an assembly when it has been loaded unless you unload the entire Application Domain.
(and if you want to know why : check this blog)
However, with a class it is different, you are talking about releasing it from memory. First of all, are you sure that no other object have an access to it ?
When you are sure of that, know that the Garbage Collector will release the memory of the unreferenced objects whenever it wants to, so talking about memory leak might be a bit prematured...
You can however force the Garbage Collector to clean up the memory by calling GC.Collect()
If we create a singleton class in a dll and use it in another dll which instantiates this singleton class, and an exe uses this dll at a point of time, will these two dlls get unloaded immediately after their job or will they get unloaded only when the main exe exits?
Disclaimer: I am not an expert on memory or processes/app domains, so I may have some specifics wrong, but I firmly believe that my conclusion is valid - feel free to comment and correct any specific errors.
No, the DLL is not unloaded until the app domain that contains it (typically the main process for windows/console apps and the web site for ASP.NET apps) is closed.
From MSDN:
There is no way to unload an individual assembly without unloading all of the application domains that contain it.
So you can manually create (and destroy) app domains, which will unload any DLLs, but then you have to marshal data across the domain boundaries, which may be worse than just keeping the DLL in memory.
The objects created by the DLL may be removed from memory (if nothing holds a reference to them), but the code itself will remain in memory. In the case of a pure singleton, it will stay in memory until the app closes (since the class that manages it will always have a reference). You could remove the reference to the singleton from the factory class, but you still may have other code that references it, so you risk having multiple instances of your "singleton". If that's not a concern, that may be a valid strategy to dispose of the singleton when you're done with it.
Think about most apps - they respond to human interaction in some way. Users can click any button, select any menu item, etc. in any order that the app allows. How is an application supposed to know for certain that code within a DLL will never get called again? Assemblies are relatively expensive to load (in part since they must be JITted), so it would be inefficient to unload them if there's any chance that they'll get loaded again.
Bottom line - since the memory footprint of a DLL is usually relatively small (since it just contains code and metadata) and is only loaded once for an entire domain, unless you experience significant memory pressure from it that can't me relived by managing other memory better, I wouldn't go to the trouble of trying to unload it.
Sometimes you need to use a particular third-party library, like in my case, one that loads up PowerPoints and allows the user to modify them in code. We discovered that this particular library has some memory leaks, but we would still like to use it because these leaks only occur in one particular scenario that occurs very rarely. You can see objects lying around despite trying to dispose all references to them, and despite having these objects go out of scope, and despite having manually invoked garbage collection. For sure, this library creates leaks. Our application is single-threaded.
Now, that being said, I am wondering if there is any way to clean up all memory that the library has used during runtime. Are there any ways to unload and reload the DLL that might cause all memory allocations from that library to be cleared, or anything that we can do at runtime at all to clean the memory that this third party library uses and then potentially reload the library in our application?
You could investigate loading the referenced library inside a custom AppDomain; an app-domain is a unit of isolation inside a process - and can be unloaded. It does, however, require you to do some communications between the two app-domains (the default domain and the hosted domain); MarshalByRefObject is the easiest trick there.
Alternatively: just use an entire separate process for this work. On windows, creating a process is relatively expensive, but not so expensive that you should never do it. Shutting down the process when done is the equivalent of nuking it from orbit. You can always re-spawn another process later.
There is an entire series of "How to" topics about AppDomain linked from MSDN here
I need to use an external assembly that I cannot modify. Suppose that I use a class from that assembly like so:
using (ExternalWidget widget = new ExternalWidget())
{
widget.DoSomething();
}
Each time I call this code, it leaks unmanaged memory. ExternalWidget implements IDisposable and I have wrapped it in a using statement, but ExternalWidget does not clean up its unmanaged resources.
Since I do not have access to the ExternalWidget code, I cannot fix this issue the right way. Is there any other way that I can free up the memory resources used by ExternalWidget?
If it is a true unmanaged memory leak and you can't change the code, then there's little that you can do. The framework can't pick up on that, nor can it clean up that code.
The approach in this case would be isolation of that component. It means there's going to be a lot of overhead in accessing it, but there's nothing else you can do.
You can't run the code in another application domain, because the unmanaged code has no concept of the application domain.
That leaves the process level. I'd recommend creating a service contract in WCF that mimics the calls to the ExternalWidget along with a Shutdown method.
Then, you would create an EXE which would expose this contract (with a session, so you can hold onto the ExternalWidget instance, unless each call is stateless) through named pipe bindings.
As a parameter to the EXE, it would take a unique identifier (use a Guid) and use that as part of setting up the endpoint for the WCF service.
Then, you would make the calls, and when you're done with that instance of ExternalWidget, call Shutdown; the EXE would know to stop waiting and then the process will exit, and the operating system will reclaim the memory.
Of course, there's a huge amount of overhead here, so if you find you're making a lot of calls and don't need a new process for each set of calls, you can expand the idea into a service which counts the calls and then recycles the process (the service will still have to shell out, or it will run out of resources) when needed.
Note that if this turns out to be a managed memory issue, then you can always spin up a new application domain, run your code there (marshaling the results back and forth as needed) and then release the application domain.
We are using EWS Managed API which polls MS Exchange for new mail messages after a given interval. With each invocation of the polling call (PullSubscription.GetEvents()) - Microsofts API is failing to properly dispose the NetworkStream and causes memory to proportionately increase. This was previously discussed here, but never resolved. Using ANTS Profiler we were able to determine which objects were continuously growing in memory and isolate the issue.
Now that the issue has been isolated - is there a way to dispose of a NetworkStream created in an external API that we don't have a reference to? GC.Collect() doesn't seem to dispose it since it still has an active reference. What can we do to cleanup the dangling reference? Is there some wrapper we can use to force cleanup of their buggy SDK?
There is no way to force GC to release memory for a referenced object!
First of all I would suggest to contact microsoft itself for help with this bug.
Second, are you talking about "disposal" or just memory release? They are two totally different things. (IDisposable pattern, finalizers).
Third, can u just dereference the object that are referencing these objects?
Fourth, one possible solution can be to decompile with reflector the code that is giving you the issue, understand a way you can arrive to the fields that are keeping the referenced objects, use reflection in your code to access the private fields and put them to null.
Is a very dirty hack, but if you have no other way is the only thing i can think of. Do this only if you cannot go in any other ways.
The most easy way would be running the part the is interfacing the SDK into its own AppDomain and after your are done unload the AppDomain. This will cause all the memory allocated in the AppDomain to be freed.
But you will need add some work to your project since you can only interchange with an AppDomain the a MarshalByRef object or marked as serilizable.
This will also allow you to monitor the amount of memory consumed by the AppDomain. So you can create your AppDomain, run the buggy SDK in it and if it reaches a special limit of memory consumption you can unload it.