我有一个外部(.Net)dll,我必须用于一个应用程序。不幸的是,dll有几个已知的内存泄漏。我们正在努力让dll的作者修复内存泄漏,但同时我想知道在不必处理内存泄漏的情况下使用dll的最佳方法是什么?
答案 0 :(得分:3)
将.Net程序集移动到它自己的AppDomain中,这样你可以定期卸载模块,如果泄漏是由于挂起对象引用“太长”,可能会有所帮助,但是我遇到的大多数“内存泄漏”情况。网络托管代码实际上无法释放非托管资源句柄 - 释放句柄,关闭文件,关闭网络连接等。
如果资源由负责的.Net托管对象拥有,该对象在IDispose.Close()中释放其非托管句柄,但某些骨头代码在调用时不会调用IDispose.Close,强制执行GC循环或卸载程序集的AppDomain可以帮助回收那些孤立的非托管资源,方法是“赶紧”对所拥有的托管对象进行最终的GC处理。
如果句柄由完全没有正确释放它们的bonehead代码拥有,则卸载程序集的AppDomain不太可能帮助回收孤立的句柄。
当进程终止时,将恢复与句柄关联的大多数Windows资源。这有点极端,但如果GC和AppDomain循环没有帮助,您可以编写一个包含有问题的.NET程序集类的包装器,并使用.NET远程处理从您的进程中完全抛弃有问题的程序集。违规程序集的类与应用程序的其余部分之间的数据交互量将决定这是否完全可行。如果违规组件是相当自包含的,具有少量接口入口点,则这可能是可行的。在自己的过程中使用违规组件,您可以定期关闭它以清除累积的残留物,而无需关闭您自己的过程。
绝对持有最后一个想法,绝对不得已。尝试找出泄露的内存或资源类型以及泄漏方式以及AppDomain循环是否会回收丢失的资源。
答案 1 :(得分:2)
除非它被混淆,否则使用.NET Reflector并取出代码,找到相关部分,修复它,重新编译它,并使用重新编译的代码。
这可能适用于您的环境,也可能不适用。如果他们拒绝我的文档,我必须弄清楚如何与一些供应商的东西接口,对我有用。但请记住,使用.NET Reflector时,您的业务可能会遇到问题。
答案 2 :(得分:1)
我不知道这是否一定适用于.NET,但是你可以卸载DLL并重新连接吗?这应该导致已分配已使用的内存(包括泄漏),然后重新加载库并以快乐的方式返回。 找到卸载DLL的时间显然很棘手。 ;)
相关链接似乎是:
答案 3 :(得分:1)
我们有一个使用第三方库(用Java开发)的服务,我们相信这个库存在内存泄漏。我们认为处理问题的简单方法是将服务分成两个不同的模块,一个是服务本身,另一个是包含业务代码,另一个是可执行文件。因此,服务循环,调用在其自己的内存空间中运行的其他可执行文件,然后完成其执行,从不使用内存泄漏来监视服务应用程序。
所以我的建议是通过缩短你使用它的时间来隔离你的程序和错误的DLL,或者改变系统的体系结构,这样你就不会直接从“长时间运行”的应用程序处理这个DLL了
答案 4 :(得分:0)
如果这是一个严重的问题,请将程序集加载到单独的AppDomain中,并单独创建您的狡猾类的实例。它还提供了一个很好的安全边界。
如果有静态成员保留变量,那么您无法对当前appdomain中的泄漏做任何事情,因此使用另一个是提供组件隔离的好方法。
将程序集加载到IAppDomain后,无法卸载它,但可以拆除整个AppDomain,GC将收集它。