【发布时间】:2023-04-03 02:35:02
【问题描述】:
我正在对 .NET 2.0 Windows 服务应用程序中的 OutOfMemory 异常进行故障排除。为了更好地理解这个问题,我首先编写了一个简单的 .NET WinForm 测试应用程序,该应用程序通过构建一个 ArrayList 直到引发 OOM 异常来生成 OOM 异常。异常被捕获并记录下来,我可以单击表单按钮再次运行 OOME。我发现奇怪的是在第 4 次运行时,下一次 OOME 之前消耗的内存量大约是一半。每次运行时,下面列出的结果都是一致的。 Eyeballing TaskManager 也确认了该行为。不幸的是,Perfmon 在试图获得更好的统计数据时冻结了。有人可以解释为什么 3 次运行后内存限制会降低吗?我对GC的理解相当肤浅。您还可以看到我在再运行几次后运行了 GC.Collect(),但它对降低限制没有帮助。
更新:我还发现对于每个数组列表项使用 const 字符串与使用新对象有很大不同。代码很简单:
const string TEST_TEXT = "xxxxxxxxxx";
ArrayList list = new ArrayList();
while (true)
{
list.Add(TEST_TEXT);
}
开始循环:内存 10,350,592
- 抛出 OOM 异常
- 数组大小:134,217,728
结束循环:内存550,408,192
开始循环:内存 550,731,776
- 抛出 OOM 异常
- 数组大小:134,217,728
结束循环:内存 551,682,048
开始循环:内存 551,813,120
- 抛出 OOM 异常
- 数组大小:134,217,728
结束循环:内存 551,772,160
开始循环:内存 551,903,232
- 抛出 OOM 异常
- 数组大小:67,108,864
结束循环:内存282,869,760
开始循环:内存 283,004,928
- 抛出 OOM 异常
- 数组大小:67,108,864
结束循环:内存 282,910,720
GC.Collect 手动触发
开始循环:内存14,245,888
- 抛出 OOM 异常
- 数组大小:67,108,864
结束循环:内存283,344,896
【问题讨论】:
-
你的测试程序到底做了什么?它是如何“构建数组”的?
-
请发布您的代码。
-
参见上面的代码示例。
-
这样的字符串字面量是实习的。对 ArrayList 的每次添加只会创建对同一内存块的新引用(此外,ArrayList 在 .Net 2.0 及更高版本中是邪恶的:不要使用它)。
-
只是好奇为什么 ArrayList 在 2.0+ 中被认为是邪恶的。与使用通用等效项相比?
标签: .net garbage-collection out-of-memory