根据 MSDN,有一个“提示”指出 .NET 应用程序运行在并发垃圾收集的重负载(
或未指定,因为它是默认行为)可能会抛出 ExecutionEngineException。有人知道 Microsoft 知识库文章或其他来源提供了这方面的更多背景吗?
我们在基于 NHibernate 3.2 的 Windows 服务应用程序中直接经历过这种情况,该应用程序最多运行几个小时后就会崩溃。我们能够追踪 ISession.Flush() 调用的异常。
nhuusers 上有一个帖子,报告了似乎相同的问题。他建议的解决方法是禁用并发 GC,尽管切换到服务器模式 GC (
)(隐式禁用并发),但到目前为止对我们来说一直有效。 GC,也达到了目的。
在将此作为 bug 提交给 MS 之前,我想了解一下是否有人有关于该提示提到的并发 GC 不稳定性的更多信息。
According to MSDN, there is a "tip" stating that a .NET application running under heavy load with concurrent garbage collection (either <gcConcurrent enabled="true"/>
or unspecified, since it's the default behavior) may throw an ExecutionEngineException. Is anyone aware of a Microsoft KB article or other source that provides additional background on this?
We have experienced this directly with an NHibernate 3.2-based Windows Service application, which will invariably crash after at most a few hours of operation. We were able to track down the exception to the ISession.Flush() call.
There's a thread on nhusers reporting what appears to be the same problem. His suggested workaround, which was to disable concurrent GC, has worked for us so far, although switching to server-mode GC (<gcServer enable="true"/>
), which implicitly disables concurrent GC, also did the trick.
Before submitting this to MS as a bug, I'd like to find out if anyone out there has additional information on the concurrent GC instablity that the tip mentions.
发布评论
评论(1)
我怀疑当应用程序负载较重时会发生这种情况,因为启用并发 GC 时,GC 会尝试在不暂停应用程序的情况下完成工作。如果 GC 遇到在 GC 周期的压缩阶段尝试移动内存但无法移动内存或无法正确更新应用程序指针的情况,则可能会导致运行时抛出此错误异常,因为它最终会使您的应用程序进入潜在无效状态。
正如 @casperOne 在他的评论中指出的那样,此异常在 .NET 4.0 中被标记为已过时,尽管这并不一定意味着 GC 仍然无法进入导致其在 .NET 3.5 中抛出异常的相同状态。如果 GC 确实进入了相同的状态,运行时将发出 FailFast 命令并终止,而不是抛出异常。
I suspect this occurs when the application is under heavy load because when concurrent GC is enabled, the GC tries to do it's work without pausing your application. If the GC encounters a situation where it tries to move memory around during the compaction phase of a GC cycle and isn't able to move the memory or isn't able to correctly update the application pointers, that could cause the runtime to throw this exception since it would end up putting your application into a potentially invalid state.
As @casperOne pointed out in his comment, this exception is marked as obsolete in .NET 4.0 although that doesn't necessarily mean the GC still can't get itself into the same state that caused it to throw the exception in .NET 3.5. If the GC did get itself into that same state, the runtime will issue a FailFast command and terminate rather than throwing an exception.