【问题标题】:C# Garbage collectionC# 垃圾回收
【发布时间】:2011-11-29 03:03:53
【问题描述】:
假设我们有:
public void foo()
{
someRefType test = new someRefType ();
test = new someRefType ();
}
垃圾收集器如何处理第一个堆对象?是否在新分配之前立即收集垃圾?一般机制是什么?
【问题讨论】:
标签:
c#
garbage-collection
heap-memory
【解决方案1】:
垃圾收集器如何处理第一个堆对象?
谁知道?这不是确定性的。可以这样想:在具有无限内存的系统上,垃圾收集器没有做任何事情。你可能认为这是一个不好的例子,但这就是垃圾收集器为你模拟的:一个具有无限内存的系统。因为在可用内存比程序所需的足够多的系统上,垃圾收集器永远必须运行。因此,您的程序无法对何时收集内存(如果有的话)做出任何假设。
所以,您的问题的答案是:我们不知道。
在新分配之前是否立即收集垃圾?
没有。垃圾收集器不是确定性的。你不知道它什么时候会收集和释放垃圾。您不能对何时收集垃圾或何时运行终结器做出任何假设。
事实上,它不太可能被这么快收集(这会使收集过于频繁)。此外,在具有足够内存的系统上,垃圾收集器从不 必须运行。
一般机制是什么?
这是一个相当广泛的问题。但其基本原理非常简单:垃圾收集器模拟一台内存无限的机器。为此,它以某种方式跟踪内存并能够确定内存何时是垃圾。当它认为合适时,由于需要模拟无限内存,它会不时收集这些垃圾并使其再次可用于分配。
【解决方案2】:
不,没有任何内容表明该对象被立即收集。事实上,这不太可能。它最终会被垃圾收集器收集,但你无法确切知道何时。
您可以通过调用 GC.Collect 来强制收集,但通常不建议这样做。
垃圾回收的具体工作原理是一个相当大的主题,但是您可以read on MSDN 找到很好的文档。
【解决方案3】:
有许多不同的垃圾收集策略,这些年来它们变得更加复杂和高效。文献和网络上有很多关于它们的优秀资源。但我也发现有时一个不完美且色彩丰富的比喻给了我一种直觉,帮助我开始。所以请允许我试一试:
.NET 有一个所谓的“分代”垃圾收集器,我认为它的行为就像我自己一样。我让脏衣服和邮件(“C# 对象”)在我的客厅地板上堆积了几天(“内存”),当我发现我再也看不到地毯时(“内存已满” )我花了一些时间清理(“垃圾收集”)起居室(“0代”),扔掉不再需要的物品(“不再可用”)并将剩余的物品移到我的卧室( “第一代”)。很多时候,这为我争取了一些时间,我不需要再做任何工作了。但是当我的卧室填满时,我会做类似的事情,扔掉一些物品并将其他物品移到我的地下室(“第 2 代”)。有时甚至地下室也会被填满,然后我遇到了真正的问题,需要进行一些大的春季大扫除(“完整收集”)。
将这个比喻应用到您的示例中,我们可能会猜测第一块垃圾(“堆对象”)只是闲置,直到我有时间捡起它(“运行第 0 代收集器”),当我感觉喜欢它,当地板被完全覆盖时,或者永远不会:-)
【解决方案4】:
要查看对象何时被删除,您可以覆盖类中的finalize 方法以打印何时以及哪些对象被删除,如下面的示例所示:
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();
}
}
要强制垃圾收集器更快地释放这些对象,您可以将一个字段作为长数组添加到它们,例如 private int []memory; 并在构造函数中:memory=new int[10000000]。