【问题标题】:Memory management while Loading assembly using reflection使用反射加载程序集时的内存管理
【发布时间】:2011-11-04 09:20:01
【问题描述】:

全部,

我正在创建一个使用复合模式的组件。核心组件使用 XML 元数据来定义组合(部件)。在运行时,核心组件会使用反射将部件组件加载到内存中并调用方法(例如 IPart.execute 方法)。

现在我的问题是

1) 使用反射加载的程序集所占用的(动态)内存将在我处置对象时被卸载。

2)如果它没有卸载并释放内存,有什么办法可以从内存中删除它。

这个问题的原因是,我正在构建的组件将是我的企业应用程序业务层的核心,可以进行大量定制。

谢谢 阿尔伯特·阿鲁尔·普拉卡什

【问题讨论】:

  • 当我们使用正则表达式时,微软表示它会创建一个动态组合,并且在应用程序/appdomain 被回收之前,该程序集不会被垃圾收集/从内存中卸载。当我们使用反射加载程序集时,它是否会创建动态程序集。如果是,那么对象将始终在内存中,并且不会优化内存的使用。这是我的担忧。可以通过适当的防御性编码和 IDIspose 等来释放资源。

标签: c# reflection memory-management composite


【解决方案1】:

我看到人们通过反射在另一个应用程序域中加载额外的库(我们可以将这些库称为“插件”)。比如看这篇文章:http://adrianvintu.com/blogengine/post/Unloadable-plugins.aspx

这样可以保护您免受“邪恶”插件的侵害,并且可以在此类 appdomain 中管理内存(当 appdomain 卸载时,内存也会被释放)

【讨论】:

  • 我从来没有使用过应用程序域。我的评论会很愚蠢。复合材料用于可以使用由顾问或系统管理员开发的更多复合材料部分的方法(例如 Company.Insert)。因此,如果我加载 Company.Insert 方法及其部分以分隔 appdomain,则在任何给定时间都可能在内存中拥有更多数量的 App 域。这不会造成性能问题吗?。
【解决方案2】:

插件/模块中有两件事会消耗内存。粗略地说,这些是代码(将程序集加载到进程空间会消耗内存)和对象(创建某事物的实例会消耗内存)。

当我处置对象时,是否会卸载使用反射加载的程序集占用的(动态)内存。

就内存而言,在IDisposable 上调用Dispose 不会对对象做任何事情。它可能会释放对象使用的资源(例如,如果您关闭文件,它将摆脱打开的文件句柄),但不会释放对象本身。 IDisposable 不是一个神奇的内存释放函数——它只是接口上的一个方法,让对象知道它应该摆脱它拥有的资源。

要释放对象本身,您必须删除对它的所有引用(可能将它们设置为 null,或者让它们从程序的堆栈中掉下来),并且垃圾收集器最终必须运行以回收该内存。

如果它没有卸载和释放内存,有什么办法可以从内存中删除它。

如果您只关心 GUI 和文件句柄等资源,请确保您致电 Dispose。你应该总是这样做:)

如果您关心对象内存,只需让 GC 完成它的工作。也不要纠缠它。让它自己运行。

如果您担心代码内存,您必须卸载代码所在的AppDomain。如果这是您的默认AppDomain,那么您无法在不退出程序的情况下卸载它。相反,您应该将该插件加载到您在运行时创建的子AppDomain 中。然后,您可以通过卸载子 AppDomain 将代码从您的进程空间中取出。

有关如何使用子AppDomain 的信息,请参阅naivists' answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-18
    • 1970-01-01
    • 2015-09-24
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    相关资源
    最近更新 更多