繁体   English   中英

ASP.NET:在某些情况下我应该担心内存泄漏吗? [C#]

[英]ASP.NET: Should I be worried about memory leaks in certain situations? [C#]

在两个对象相互引用的情况下,我关注垃圾收集......

public class A
{   public readonly B _b;
    public A()
    {   _b = new B(this);
    }
}

public class B
{   public readonly A _a;
    public B(A objA)
    {   _a = objA;
    }
}

在这种情况下,第三类可以引用A ...

public class Foo
{   public A _a = new A(); // A and B are both created here.
    public void Bar()
    {   _a = new A();
    }   // Create a new A (and B)
}

通常,垃圾收集器会处理不再具有任何活动引用的对象。 但在这种情况下,A和B对象永远不会丢失所有活动引用,因为它们总是相互引用。

Foo对象用新的A (和B )替换当前的A (和B )时,垃圾收集器是否能够清除旧的A (和B )而不用循环对象引用启动无限循环?

这是一个严重的问题,因为它是一个ASP.NET应用程序。 这些对象将在每个Web请求中多次创建,并且如果垃圾收集器无法清除它们,则可能会延迟服务器重新启动。
可能的负面结果:
<<由于RAM溢出,Web服务器崩溃。
<< Webserver因无限垃圾收集循环而崩溃。

在这种情况下,.NET如何处理垃圾收集?

.NET GC通过跟踪有根引用来工作,例如静态字段和范围内局部变量。 它正确处理参考周期。 例如,如果A < - > B,但都没有从有根参考引用,则会收集它。

让我们考虑GC如何确定它何时可以回收内存。 当CLR尝试分配内存并且内存不足时,它会执行垃圾回收。 GC枚举所有有根引用,包括任何线程调用堆栈上的静态字段和范围内局部变量。 它将这些引用标记为可访问,并遵循这些对象包含的任何引用,并将它们标记为可访问。 它继续此过程,直到它访问了所有可访问的引用。 任何未标记的对象都是不可访问的,因此是垃圾。 GC压缩托管堆,整理引用以指向它们在堆中的新位置,并将控制权返回给CLR。 如果释放了足够的内存,则使用此释放的内存继续分配。 如果不是,则从操作系统请求额外的内存。

- 来自http://msdn.microsoft.com/en-us/magazine/cc163491.aspx

如果A - > B,B - > A并且没有对A和B的其他引用,则GC足够智能以释放这些对象。

在ASP.NET中,增加了应用程序池的保险。 应用程序的许多实例保存在内存中,并根据需要分配给各种会话。 有时,即使在会话的上下文中,IIS也会决定刷新应用程序池的好时机。 当会话结束时,IIS通常会关闭并重新启动应用程序,如果它与每个应用程序,每个池或整个系统内存限制相冲突。 有时这甚至发生在会话中间; 这在SOA中很常见,其中外部Web层通过WCF与另一个服务器通信,并且服务层可以在Web层的调用之间刷新。

.NET Garbage收集器可以毫无问题地清除循环引用。

它不计算对旧VB6 GC等对象的引用。
它通过从特殊的“对象根”开始遍历内存中的所有对象来跟踪活动对象。

更简单地说:

当垃圾收集器运行时,它从内存寄存器和静态字段等开始。 这些被称为“根”。

从那里,垃圾收集器跟随从根到其他对象实例的引用。 这将创建从根可到达的所有对象的图形。

如果您的对象无法从根目录访问,那么它们将被视为未引用,并且可以由垃圾收集器清理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM