all groups > dotnet clr > may 2007 >
You're in the dotnet clr group:
Prematurely garbage collection
dotnet clr:
Hi. In what cases is it possible that the GC will collect an object while a member of that object is still running? Could it happen when I create an object without referencing it and then invoking one of its members? For example: (new Instance()).Invoke(); // there's no reference to the
[quoted text, click to view] Amir Shitrit <AmirShitrit@discussions.microsoft.com> wrote: > In what cases is it possible that the GC will collect an object while a > member of that object is still running?
If the JIT can prove that it won't be accessing any of its fields any more. [quoted text, click to view] > Could it happen when I create an object without referencing it and then > invoking one of its members? > For example: (new Instance()).Invoke(); // there's no reference to the > Instance object.
That entirely depends on what Invoke does. It has an implicit reference to "this", but at the point where the JIT can spot that it's not going to use any more fields (or call anything else that will use those fields) the object is eligible for GC. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
"Amir Shitrit" <AmirShitrit@discussions.microsoft.com> ha scritto nel messaggio news:B080FE00-AB05-4A60-A836-6600892BAF9B@microsoft.com... [quoted text, click to view] > Hi. > In what cases is it possible that the GC will collect an object while a > member of that object is still running?
Depends what you mean by "object is still running", but pratically it cannot happen, in all managed code world. [quoted text, click to view] > Could it happen when I create an object without referencing it and then > invoking one of its members?
No, because it's not possible to invoke a member without a reference (implicit or explicit) to the object. [quoted text, click to view] > For example: (new Instance()).Invoke(); // there's no reference to the > Instance object.
The (new Instance()) will be kept alive until Invoke() returns.
Hi, 1. GC will not recollect the memory assigned to running object. 2. if you open IL of code '(new Instance()).Invoke();', you can see clr gives a random generated name for this instance. use ildasm.exe to verify it. I hope this answers your question Regards Chitrsen
[quoted text, click to view] Chitrsen wrote: > 1. GC will not recollect the memory assigned to running object.
Actually, it can, if the remaining code path in methods of the instance don't access the 'this' reference. [quoted text, click to view] > 2. if you open IL of code '(new Instance()).Invoke();', you can see clr > gives a random generated name for this instance. use ildasm.exe to verify it.
This doesn't mean anything. The JIT needs to allocate a register or a stack slot and store a reference where the GC can find it, in order to prevent collection. If the code doesn't access the reference, the JIT compiler can optimize the reference away. The IL is just input to the JIT compiler. [quoted text, click to view] > I hope this answers your question
Be careful that your answers are correct! Check out the following program (compile with 'csc test.cs' if saved to test.cs): ---8<--- using System; class C { ~C() { Console.WriteLine("Collected!"); } static void Main() { new C().Use(); } void Use() { GC.Collect(); GC.WaitForPendingFinalizers(); Console.WriteLine("Used!"); } } --->8--- Run it and it results in: ---8<--- Collected! Used! --->8--- -- Barry --
That's a pretty evil example. I wouldn't have thought of it... I'll have to save that one off as an Interview question one day. "What will this print out?" -- Chris Mullins, MCSD.NET, MCPD:Enterprise, Microsoft C# MVP http://www.coversant.com/blogs/cmullins [quoted text, click to view] "Jon Skeet [C# MVP]" <skeet@pobox.com> wrote in message news:MPG.20b8326cc9c8494d128@msnews.microsoft.com... > Chitrsen <Chitrsen@discussions.microsoft.com> wrote: >> 1. GC will not recollect the memory assigned to running object. > > Yes it can. > >> 2. if you open IL of code '(new Instance()).Invoke();', you can see clr >> gives a random generated name for this instance. use ildasm.exe to >> verify it. > > It can still be garbage collected before Invoke() has finished > executing. Here's an example: > > using System; > using System.Threading; > > class Test > { > ~Test() > { > Console.WriteLine ("Finalizer"); > } > > void Invoke() > { > Console.WriteLine ("Start of method"); > GC.Collect(); > GC.WaitForPendingFinalizers(); > > Console.WriteLine ("Called GC"); > > Thread.Sleep(1000); > Console.WriteLine ("End of method"); > } > > > static void Main() > { > new Test().Invoke(); > } > } > > On my box that prints: > Start of method > Finalizer > Called GC > End of method > > -- > Jon Skeet - <skeet@pobox.com> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > If replying to the group, please do not mail me too
[quoted text, click to view] "Jon Skeet [C# MVP]" <skeet@pobox.com> wrote > Chris Mullins [MVP] <cmullins@yahoo.com> wrote: >> I'll have to save that one off as an Interview question one day. "What >> will >> this print out?" > > I wouldn't use these as interview questions to see whether the > candidate knows the answer. They are, however, quite good questions to > see how *interested* the candidate is in little bits of obscure > knowledge.
I tend to ask questions like this to see: 1 - How does the candidate do out of their confort zone? Do they get hostile? angry? confrontational? Or do they just think about it an go, "Hmmm. Good question.". 2 - I like to see how people think. Critical thinking is just... key. An answer of "I don't know, but I think the answer is xyz, for these reasons..." is just fine with me, even if the answer is actually wrong. Being somewhat of a jerk, I've also told candidates wong information just to see what approach they would take to correct me. If I'm going to be stuck working with someone for a while, I consider these important things to know... -- Chris Mullins, MCSD.NET, MCPD:Enterprise, Microsoft C# MVP http://www.coversant.com/blogs/cmullins
[quoted text, click to view] Chitrsen <Chitrsen@discussions.microsoft.com> wrote: > 1. GC will not recollect the memory assigned to running object.
Yes it can. [quoted text, click to view] > 2. if you open IL of code '(new Instance()).Invoke();', you can see clr > gives a random generated name for this instance. use ildasm.exe to verify it.
It can still be garbage collected before Invoke() has finished executing. Here's an example: using System; using System.Threading; class Test { ~Test() { Console.WriteLine ("Finalizer"); } void Invoke() { Console.WriteLine ("Start of method"); GC.Collect(); GC.WaitForPendingFinalizers(); Console.WriteLine ("Called GC"); Thread.Sleep(1000); Console.WriteLine ("End of method"); } static void Main() { new Test().Invoke(); } } On my box that prints: Start of method Finalizer Called GC End of method -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] Chris Mullins [MVP] <cmullins@yahoo.com> wrote: > That's a pretty evil example. > > I wouldn't have thought of it... > > I'll have to save that one off as an Interview question one day. "What will > this print out?"
The difference an empty static constructor makes is an equally evil example: http://www.yoda.arachsys.com/csharp/beforefieldinit.html This blog entry has a few too: http://msmvps.com/blogs/jon.skeet/archive/2005/10/02/68716.aspx I wouldn't use these as interview questions to see whether the candidate knows the answer. They are, however, quite good questions to see how *interested* the candidate is in little bits of obscure knowledge. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Do you mean that altough the method has a pointer to "this" as a method argument, the jitter can still unreference this argument? [quoted text, click to view] "Barry Kelly" wrote: > Chitrsen wrote: > > > 1. GC will not recollect the memory assigned to running object. > > Actually, it can, if the remaining code path in methods of the instance > don't access the 'this' reference. > > > 2. if you open IL of code '(new Instance()).Invoke();', you can see clr > > gives a random generated name for this instance. use ildasm.exe to verify it. > > This doesn't mean anything. The JIT needs to allocate a register or a > stack slot and store a reference where the GC can find it, in order to > prevent collection. If the code doesn't access the reference, the JIT > compiler can optimize the reference away. The IL is just input to the > JIT compiler. > > > I hope this answers your question > > Be careful that your answers are correct! > > Check out the following program (compile with 'csc test.cs' if saved to > test.cs): > > ---8<--- > using System; > > class C > { > ~C() > { > Console.WriteLine("Collected!"); > } > > static void Main() > { > new C().Use(); > } > > void Use() > { > GC.Collect(); > GC.WaitForPendingFinalizers(); > Console.WriteLine("Used!"); > } > } > --->8--- > > Run it and it results in: > > ---8<--- > Collected! > Used! > --->8--- > > -- Barry > > -- > http://barrkel.blogspot.com/
If an object has a reference available from an application root, it will not be collected. In the example below, when Invoke is being executed, the reference of the instance is available with app root - so the object is not collected until there are no more pending references. Executing the example given by Jon below on my machine gave the following output: Start of method Called GC End of method Finalizer To better illustrate this point, see the attached file that contains a modified version of the example below. As expected, the output is: Start of method Finalizer of 1 Called GC End of method Finalizer of 2 -- Thanks! Gaurav WinToolZone - http://www.wintoolzone.com/ Inside and Out - http://www.wintoolzone.com/blog/ The information in this post is provided "AS IS" with no warranties, and confers no rights. [quoted text, click to view] "Jon Skeet [C# MVP]" <skeet@pobox.com> wrote in message news:MPG.20b8326cc9c8494d128@msnews.microsoft.com... > Chitrsen <Chitrsen@discussions.microsoft.com> wrote: >> 1. GC will not recollect the memory assigned to running object. > > Yes it can. > >> 2. if you open IL of code '(new Instance()).Invoke();', you can see clr >> gives a random generated name for this instance. use ildasm.exe to >> verify it. > > It can still be garbage collected before Invoke() has finished > executing. Here's an example: > > using System; > using System.Threading; > > class Test > { > ~Test() > { > Console.WriteLine ("Finalizer"); > } > > void Invoke() > { > Console.WriteLine ("Start of method"); > GC.Collect(); > GC.WaitForPendingFinalizers(); > > Console.WriteLine ("Called GC"); > > Thread.Sleep(1000); > Console.WriteLine ("End of method"); > } > > > static void Main() > { > new Test().Invoke(); > } > } > > On my box that prints: > Start of method > Finalizer > Called GC > End of method > > -- > Jon Skeet - <skeet@pobox.com> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] Gaurav Khanna [MSFT] <gkhanna@microsoft.com.nospam> wrote: > If an object has a reference available from an application root, it > will not be collected. In the example below, when Invoke is being > executed, the reference of the instance is available with app root - > so the object is not collected until there are no more pending > references.
Well, until there are no more pending references which might be used.The JIT is able to detect when the currently executing no longer actually uses its implicit "this" reference, which is why it can give the output I showed before. [quoted text, click to view] > Executing the example > given by Jon below on my machine gave the following output: > > Start of method > Called GC > End of method > Finalizer
How were you running it? If you run it in the debugger, you'll always see the above. [quoted text, click to view] > To better illustrate this point, see the attached file that contains a > modified version of the example below. As expected, the output is: > > Start of method > Finalizer of 1 > Called GC > End of method > Finalizer of 2
It may be for you, but compiling with csc Test.cs /o+ /debug- and then running I got: Start of method Finalizer of 2 Finalizer of 1 Called GC End of method Again, it will depend on how you're running the code. I always run this kind of thing from the command line, to closer mirror production situations (compared with running from Visual Studio, where you have to be careful not to end up using the debugger). Just to give a bit more evidence that I'm not making this stuff up, see this blog entry by Chris Brumme: http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
"Jon Skeet [C# MVP]" <skeet@pobox.com> ha scritto nel messaggio news:MPG.20ba7bed8b3b8597131@msnews.microsoft.com... [quoted text, click to view] > Gaurav Khanna [MSFT] <gkhanna@microsoft.com.nospam> wrote: >> If an object has a reference available from an application root, it >> will not be collected. In the example below, when Invoke is being >> executed, the reference of the instance is available with app root - >> so the object is not collected until there are no more pending >> references. > > Well, until there are no more pending references which might be > used.The JIT is able to detect when the currently executing no longer > actually uses its implicit "this" reference, which is why it can give > the output I showed before. >
So we can safely say that there is no "Premature garbage collection" as the OP's title states. [quoted text, click to view] >> Executing the example >> given by Jon below on my machine gave the following output: >> >> Start of method >> Called GC >> End of method >> Finalizer > > How were you running it? If you run it in the debugger, you'll always > see the above. > >> To better illustrate this point, see the attached file that contains a >> modified version of the example below. As expected, the output is: >> >> Start of method >> Finalizer of 1 >> Called GC >> End of method >> Finalizer of 2 > > It may be for you, but compiling with csc Test.cs /o+ /debug- > and then running I got: > > Start of method > Finalizer of 2 > Finalizer of 1 > Called GC > End of method > > Again, it will depend on how you're running the code. I always run this > kind of thing from the command line, to closer mirror production > situations (compared with running from Visual Studio, where you have to > be careful not to end up using the debugger). > > Just to give a bit more evidence that I'm not making this stuff up, see > this blog entry by Chris Brumme: > > http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx > > -- > Jon Skeet - <skeet@pobox.com> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > If replying to the group, please do not mail me too
[quoted text, click to view] Laura T. <laura_ttx@yahoo.com> wrote: > > Well, until there are no more pending references which might be > > used.The JIT is able to detect when the currently executing no longer > > actually uses its implicit "this" reference, which is why it can give > > the output I showed before. > > So we can safely say that there is no "Premature garbage collection" as the > OP's title states.
It's premature compared with the OP's *expectation* which is pretty important, IMO. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] Laura T. wrote: > "Jon Skeet [C# MVP]" <skeet@pobox.com> ha scritto nel messaggio > news:MPG.20ba7bed8b3b8597131@msnews.microsoft.com... > > Well, until there are no more pending references which might be > > used.The JIT is able to detect when the currently executing no longer > > actually uses its implicit "this" reference, which is why it can give > > the output I showed before. > > So we can safely say that there is no "Premature garbage collection" as the > OP's title states.
It's still very important if you have expectations of when the finalizer will be executed or when weak references will be null'd - and they're pretty much the only observable side-effects of garbage collection. If the OP has a reason to wonder about when GC happens, and when an object is collected, chances are that he needs to know the details here. -- Barry --
Don't see what you're looking for? Try a search.
|
|
|