C# Garbage collection
Say we have:
public void foo()
{
someRefType test = new someRefType ();
test开发者_JAVA百科 = new someRefType ();
}
What does the garbage collector do with the first heap object? Is it immediately garbage collected before the new assignment? What is the general mechanism?
What does the garbage collector do with the first heap object?
Who knows? It's not deterministic. Think of it like this: on a system with infinite memory, the garbage collector doesn't have to do anything. And you might think that's a bad example, but that's what the garbage collector is simulating for you: a system with infinite memory. Because on a system with sufficiently more memory available than required by your program, the garbage collector never has to run. Consequently, your program can not make any assumptions about when memory will (if ever) be collected.
So, the answer to your question is: we don't know.
Is it immediately garbage collected before the new assignment?
No. The garbage collector is not deterministic. You have no idea when it will collect and release garbage. You can not make any assumptions about when garbage will be collected or when finalizers will run.
In fact, it's very unlikely it's collected so quickly (that would make collections happen too frequently). Additionally, on a system with sufficient memory, the garbage collector never has to run.
What is the general mechanism?
That's a fairly broad question. But the underlying principle is very simple: a garbage collector simulates a machine with infinite memory. To do this, it somehow keeps track of memory and is able to determine when memory is garbage. When it sees fit, due to its need to simulate infinite memory, it will from time to time collect this garbage and make it available for allocation again.
No, there is nothing that says that the object is immediately collected. In fact, it is quite unlikely that it is. It will be collected eventually by the garbage collector, but you can't know exactly when.
You can force a collection by calling GC.Collect
, although this is normally not recommended.
Exactly how the garbage collection works is a fairly large subject, but there is great documentation you can read on MSDN.
There are numerous different strategies for garbage collection and they have gotten more sophisticated and more efficient over the years. There's lots of excellent resources in the literature and on the web that talk about them. But I also find sometimes an imperfect and colorful metaphor gives me an intuition that helps me get started. So allow me to try:
.NET has a so-called "generational" garbage collector and I think of it as behaving I lot like I do myself. I let dirty clothes and mail ("C# objects") pile up all over my living room floor ("memory") over a period of several days and when I find that I can't see the carpet any more ("memory full") I spend some time cleaning up ("garbage collecting") the living room ("generation 0"), throwing away the objects that aren't needed any more ("no longer reachable") and moving the remaining ones to my bedroom ("generation 1"). Quite often this buys me some time and I don't need to do any more work. But when my bedroom fills up I do something similar, throwing away some objects and moving the others to my basement ("generation 2"). Occasionally even the basement fills up and then I have I real problem and need to do some major spring cleaning ("full collection").
Applying this metaphor to your example, we might guess that the first piece of trash ("heap object") just sits around until I get around to picking it up ("run the generation 0 collector") which happens when I feel like it, when the floor gets completely covered, or maybe never :-)
To see when the objects are being deleted, you can override the finalize method in your class to print when and what objects are being deleted, like in this sample below:
class MyClass
{
private int _id;
public MyClass(int id)
{
_id = id;
}
~MyClass()
{
Console.WriteLine("Object " + _id + " deleted at " + DateTime.Now + " .");
}
}
class Program
{
static void Main(string[] args)
{
MyClass p1 = new MyClass(1);
p1 = new MyClass(2);
Console.ReadKey();
}
}
To force the garbage collector to free this objects faster, you could add a field to them as a long array, something like private int []memory;
and in the constructor: memory=new int[10000000]
.
精彩评论