从程序集创建实例会引发内存泄漏

时间:2015-06-12 12:05:58

标签: .net reflection memory-leaks

我有一个桌面应用程序,我需要在不同的AppDomain中使用反射加载一些dll,调用方法并卸载AppDomain。我已经正确开发了它,但是我最近需要加载和卸载的程序集数量已经增加,现在,在加载3 dll后,当我尝试加载第4个dll时,我得到了这个例外:

System.TypeInitializationException: An exception occurred on startup type '<Module>'. ---> System.AccessViolationException: Attempted to read or write protected memory. This often indicates that other memory is corrupt.

en .cctor()

--- End of monitoring the inner exception stack ---

en System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)

en System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)

en System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)

en System.Activator.CreateInstance(Type type, Boolean nonPublic)

en System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)

en System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)

en System.Reflection.Assembly.CreateInstance(String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)

en BankIntegration.ReflectionCaller.CallInternal(String dll, String typename, String method, Object[] parameters)

en BankIntegration.ReflectionCaller.CallInternal(String dll, String typename, String method, Object[] parameters)

en BankIntegration.ReflectionCaller.Call(String pathToDLL, String typename, String method, Object[] parameters)

en BankIntegration.DllManager.init_bank_conectors(Server service)

en BankIntegration.frmClient..ctor(Server service, String dllPath, Int64 idclient)

en AVISync.frmInit.Button_clicked(Object sender, ItemClickEventArgs e)

在网上搜索后,我甚至无法确定问题所在。如果我在visual studio上调试应用程序,它可以正常工作。它仅出现在已发布的应用程序中。这是相关的代码:

“DLLManager:

For Each bean As BankIntegration.AppUtil.bankBean In aux
        Dim dllPath As String = Path.Combine(DLL_FILES_DIR, bean.DllName)
        Dim download As Boolean = False

        If File.Exists(dllPath) Then
            Dim info As BankInterfaces.beans.DLLInfo = ReflectionCaller.Call(dllPath, bean.DllNameSpace & ".Connector", BankInterfaces.Util.BANKINTERFACE_NAMES.getDLLInfo, Nothing)
            'Irrelevant code here'
            info = Nothing
            'Irrelevant code here'
        End If

            'Irrelevant code here'
        GC.Collect()
    Next

“ReflectionCaller

Public Shared Function [Call](ByVal pathToDLL As String, ByVal typename As String, ByVal method As String, ByVal ParamArray parameters As Object()) As Object
    Dim permissions As New Security.PermissionSet(Security.Permissions.PermissionState.Unrestricted)
    Dim adSetup As New AppDomainSetup()
    adSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory
    Dim dom As AppDomain = AppDomain.CreateDomain(Guid.NewGuid.ToString, AppDomain.CurrentDomain.Evidence, adSetup, permissions)
    Dim ld As ReflectionCaller = DirectCast(dom.CreateInstanceAndUnwrap(Reflection.Assembly.GetExecutingAssembly().FullName, GetType(ReflectionCaller).FullName), ReflectionCaller)
    Dim result As Object = ld.CallInternal(pathToDLL, typename, method, parameters)

    AppDomain.Unload(dom)
    dom = Nothing
    ld = Nothing
    GC.Collect()
    Return result
End Function

Private Function CallInternal(dll As String, typename As String, method As String, parameters As Object()) As Object
    Dim a As Reflection.Assembly = Reflection.Assembly.LoadFile(dll)
    Dim o As Object = a.CreateInstance(typename) '<-- This line throws the exception after a few iterations'
    Dim t As Type = o.[GetType]()
    Dim m As Reflection.MethodInfo = t.GetMethod(method)
    Dim result As Object = m.Invoke(o, parameters)

    a = Nothing
    o = Nothing
    t = Nothing
    m = Nothing
    GC.Collect()
    Return result
End Function

1 个答案:

答案 0 :(得分:1)

在网上搜索2天后,我就能解决错误。对于我的情况,这是任何人的解决方案。

  1. 您希望通过反射加载的类必须实现IDisposable接口。
  2. 这些类必须覆盖Dispose方法。在这个方法中,只需强制垃圾收集器:

    GC.Collect(3)
    GC.SuppressFinalize(Me)