【发布时间】:2010-04-21 12:58:40
【问题描述】:
我知道 .Net 托管世界中的静态对象被加载到永远不会被垃圾回收的加载器堆中。
传递给静态方法的实例引用参数会发生什么。一旦静态函数完全执行,它们是否会被垃圾收集,或者它们将永远存在,因为这些实例引用变量一旦传递给静态方法?
今晚我真的很困惑;请指导我。
感谢和问候
123 开发人员。
【问题讨论】:
我知道 .Net 托管世界中的静态对象被加载到永远不会被垃圾回收的加载器堆中。
传递给静态方法的实例引用参数会发生什么。一旦静态函数完全执行,它们是否会被垃圾收集,或者它们将永远存在,因为这些实例引用变量一旦传递给静态方法?
今晚我真的很困惑;请指导我。
感谢和问候
123 开发人员。
【问题讨论】:
是的,它们在静态函数执行后被垃圾回收。您正在非静态上下文中创建对象,因此它们不是在加载程序堆中创建的。只是将引用传递给静态函数并不会改变任何东西。
【讨论】:
您将引用传递给静态方法并不意味着该对象将以任何方式植根,因此仅凭这一点不足以阻止它被收集。
是否可以在方法调用期间或仅在完成后收集,取决于方法对参数的作用,以及对象是否在方法调用之外使用。
例如,考虑这个假设的代码:
public static class Program()
{
public static void Main()
{
SomeObject o = new SomeObject();
OtherMethod(o);
}
private static void OtherMethod(SomeObject x)
{
// lots of code here, but none that uses x
}
}
在这种情况下,可以在调用OtherMethod 期间收集 o,前提是您编译并运行发布版本。对于发布版本,不再使用的变量和参数,即没有使用它的代码,被认为是死的,因此在检查是否有对对象的实时引用时不再计算在内。
在 Debug 构建中,所有变量和参数都会人为地保持活动状态,直到方法返回,这样您就可以设置断点并检查变量,即使没有使用它的代码。
因此,如果您要从调试版本运行上述代码,则该对象将一直保持活动状态,直到 Main 返回。
【讨论】:
一旦静态方法处理完变量,它就不再持有对它的引用(如果将它分配给静态变量,那就不同了)。但这并不意味着它会立即被垃圾收集。除非您明确告诉 GC 运行,否则它何时运行取决于运行时认为何时需要释放内存。说实话,这在应用程序的生命周期中可能永远不会发生(资源将随着应用程序的结束而被释放)。然而,这极不可能,尽管在技术上是可行的。
【讨论】: