[英]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。 如果释放了足够的内存,则使用此释放的内存继续分配。 如果不是,则从操作系统请求额外的内存。
如果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.