我们有一个 Web 服务,它使用越来越多的私有字节,直到该应用程序停止响应。托管堆(主要是 Gen2)将显示大约 200-250 MB,而私有字节显示超过 1GB。托管堆外内存泄漏的可能原因是什么?
我已经检查了以下内容:
- 多产的动态程序集(Xml 序列化、正则表达式等)
- 会话状态(关闭)
- System.Policy.Evidence 内存泄漏(已安装 SP1)
- 线程死锁(不使用Join,只使用锁)
- SQLOLEDB的使用(使用SqlClient)
我可以检查哪些其他来源?
我们有一个 Web 服务,它使用越来越多的私有字节,直到该应用程序停止响应。托管堆(主要是 Gen2)将显示大约 200-250 MB,而私有字节显示超过 1GB。托管堆外内存泄漏的可能原因是什么?
我已经检查了以下内容:
我可以检查哪些其他来源?
确保您的应用在发布模式下符合要求。如果您在调试模式下编译并部署它,只需实例化一个定义了事件的类(甚至不需要引发事件),将导致一小块内存泄漏。在足够长的时间内实例化足够多的这些对象将导致所有内存都被使用。我见过 Web 应用程序会在几个小时内耗尽所有内存,这仅仅是因为使用了调试版本。立即编译为发布版本并永久修复了该问题。
直到由于可用内存不足而拒绝内存请求时,垃圾收集才会运行。当一个人不在时,这通常会使事情看起来像内存泄漏。
服务中是否有任何事件和事件处理程序?服务通常有静态变量,如果你从静态实例创建事件处理程序,连接到非静态实例对象,静态将永远持有对实例的引用,这将阻止它释放。
同时寻找:
尝试强制垃圾收集器 (GC) 运行(编写一个在加载时执行此操作的页面)或尝试检测,但根据我的经验,这有点命中注定。另一件事是让它保持运行,看看它是否内存不足。
可能发生的情况是内存充足,而 Windows 没有发出要清理您的应用程序的信号。这导致应用程序看起来使用越来越多的内存,因为它可以,而实际上系统可以在需要时回收内存。SQL Server 和 Exchange 经常这样做。这个想法是为什么在有大量资源时导致不必要的清理。
抢
我建议您在不同时间查看堆栈的快照,并查看哪些内容正在耗尽内存。如果您的应用程序使用 Java,那么 jmap 工作得非常好——您只需为其提供 java 进程的 PID。
如果使用其他东西,请尝试 Lambda Probe ( http://www.lambdaprobe.org/d/index.htm )。它没有显示太多细节,但至少会显示内存使用情况。
我的 JDBC 代码中存在严重的内存泄漏,最终被追踪到几年前我错过的 JDBC 规范的更改(关于关闭语句等)。它结合了 Lamdba Probe 和 jmap 来定位问题,足以解决它。
干杯,
-R
仔细检查是否未启用跟踪。我已经看到跟踪实例缓慢消耗内存,直到应用程序达到其应用程序池限制。
对于它的价值,我的问题不在于服务,而在于调用它的 HttpClient。
客户端未正确处理,因此它保持连接打开并锁定内存。
处理客户端后,服务按预期释放内存。