Unloading an AppDomain

  • Thread starter Thread starter Phil Jones
  • Start date Start date
P

Phil Jones

SCENARIO: I'm creating a new AppDomain, loading an assembly in it, and then
creating a remoting proxy object that I'm using to communicate with the
assembly loaded within the new appdomain (I'm calling this a "Satellite").

The problem is, when I Unload the AppDomain (and then call GC.Collect) the
memory is not being freed up.

I'm disposing the Satellite proxy object before I do this. Is there
something I'm missing here? Would the AppDomain perhaps not be unloaded
properly for some reason. Perhaps threading issues? I wonder if anyone has
any insights into this problem.

Thanks everyone
===
Phil
 
My information is that there may be a slight memory leak (approx 16 bytes)
but nothing major. You should not need to call GC.Collect. Are you making
any calls to unmanaged code in the other appdomain? If a thread cannot be
unwound then it could hang as it unloads, but you should get an eventual
exception due to a timeout.

Make sure that you are truly isolating all objects and assemblies within
the 2nd appdomain. In other words, do not do this...
// from default appdomain...
Assembly a = otherAppDomain.Load("fullname");

returning a reference causes the assembly to get loaded in both appdomains.

This linke describes appdomains - you might get some info here.
http://www.gotdotnet.com/team/clr/LoadFromIsolation.aspx

Chris Brumme has written extensively on this subject - check out his blogs.
http://blogs.msdn.com/cbrumme
 
I'm suspecting that it's something related to the problem you point out
(assembly loading in both app-domains, or a reference that prevents the
other app-domain to unload).

I'm not doing what you point out - I'm creating a remoting reference to the
object using

AppDomain.CreateInstanceAndUnwrap([assembly].ToString, [type])

My understanding is that this creates a remoting proxy to an object in the
other app-domain. It certainly works that way - but I wonder if that's
preventing the App-domain from releasing memory when unloaded.


Thanks for your thoughts David
===
Phil
 
If this is what you are doing...
AppDomain.CreateInstanceAndUnwrap([assembly].ToString, [type])

then in the fragment [assembly].ToString(),. if [assembly] is the reference
to the assembly itself then this would cause it to get loaded in both
appdomains. You need to make absolutely certain that you are not actually
using a reference to the assembly itself unless you fully intend it to get
loaded in both appdomains.

Also, simply holding a reference to a proxy should not prevent the appdomain
from unloading - it might invalidate the proxy but that's about it (AFAIK).

How do you know you've got a memory leak?
 
I see your point. I'm actually loading a copy of the loaded assembly in the
other app-domain, and so you're right - it will be loaded in both places.

But apart from being loading in domains - there shouldn't be any
relationship between them other than the proxy object resulting from the
"CreateInstanceAndUnwrap" method (would that be correct??).

The reason I'm doing this is so that I can initialize a new copy of the
assembly to talk to a remoting server. If the server is not there, then I
unload the app-domain. Apart from this problem - I've found that is a clean
way to handle the issue of a stale server.

I'm running a polling routine - which repeats this process over and over in
an attempt to re-connect, which is where I'm noticing the memory-leak as the
size of the processe's memory usage just keeps going up.

Thanks David.
==
Phil
 
Phil Jones said:
I see your point. I'm actually loading a copy of the loaded assembly in
the other app-domain, and so you're right - it will be loaded in both
places.

But apart from being loading in domains - there shouldn't be any
relationship between them other than the proxy object resulting from the
"CreateInstanceAndUnwrap" method (would that be correct??).

The reason I'm doing this is so that I can initialize a new copy of the
assembly to talk to a remoting server. If the server is not there, then I
unload the app-domain. Apart from this problem - I've found that is a
clean way to handle the issue of a stale server.

I'm running a polling routine - which repeats this process over and over
in an attempt to re-connect, which is where I'm noticing the memory-leak
as the size of the processe's memory usage just keeps going up.

How much is it going up by? As I said I am aware of a small leak but that
does not mean that there may not be other leaks. If it is a large leak then
you should look at your code talking to the server to ensure that it is not
allocating an unmanaged object that is not getting released.

Personally, I'd be wary of creating and destroying a large quantity of
appdomains in an application that was intended to remain running for very
long periods of time, at least in version 1.1.
 
Personally, I'd be wary of creating and destroying a large quantity of
appdomains in an application that was intended to remain running for very
long periods of time, at least in version 1.1.

OK, that's good to know - I'll think of another way around this. The memory
usage is jumping up about 1MB each time I create/shutdown the domain.
Everything inside the app-domain is native .NET objects (no COM interop).
Would that still qualify for a memory leak??

I appreciate all you help on this David!
Thanks
====
Phil
 
Yah, that's a memory leak all right. Without detailed information I have no
idea what could cause it, but I'd suggest using some memory probes on it.
There are some free tools and also some commercial tools you can use. I'd
start with the free ones and try to narrow it down. At a minimum you need to
find out what objects are using up that memory.
 
Hi David,

Do you have any prefs or suggestions on a good "free memory profiling tool"
to start off with?

Many thanks for your help with all of this!
===
Phil
 
Back
Top