从程序集创建实例会引发内存泄漏 [英] Creating an instance from assembly throws a memory leak
问题描述
我有一个桌面应用程序,需要在其他AppDomain中使用反射加载一些dll,调用一个方法并卸载AppDomain.我已经正确开发了它,但是最近需要加载和卸载的程序集数量有所增加,现在,在加载3个dll之后,当我尝试加载第4个dll时,出现此异常:
I have a desktop application where i need to load some dll using reflection in a different AppDomain, call a method and unload the AppDomain. I have correctly developed it, however the number of assemblies i need to load and unload has been increased recently, and now, after loading 3 dll, when i try to load the 4th dll I get this exception:
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上调试应用程序,则它可以正常运行.它仅出现在已发布的应用程序上.这是相关代码:
After searching on the net, i can't even figure what's the problem. If I debug the application on visual studio it works properly. It only appear on the published application. This is the relevant code:
'DLLManager:
'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
'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
推荐答案
在网上搜索2天后,我已经能够解决该错误.这是针对我情况的任何人的解决方案.
After 2 days searching on the net i have been able to resolve the error. This is the solution for anyone on my situation.
- 要通过反射加载的类必须实现IDisposable接口.
-
这些类必须重写Dispose方法.在这种方法中,只需强制垃圾收集器即可:
- The classes you want to load by reflection have to implement the IDisposable interface.
These classes have to override the Dispose method. In this method, simply force the garbage collector:
GC.Collect(3)
GC.SuppressFinalize(Me)
这篇关于从程序集创建实例会引发内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!