C# 内存泄漏,为什么我的终结队列中有这么多ReaderWriterLock对象?

C# 内存泄漏,为什么我的终结队列中有这么多ReaderWriterLock对象?,c#,service,memory-leaks,windbg,C#,Service,Memory Leaks,Windbg,我有一个内存泄漏的.NET windows服务应用程序 概述: 该服务通过TCP连接到另一个服务,并将数据写入SQL server数据库。该服务通常在100到300 MB之间运行,这取决于它排队的数据量。通常需要3天以上的时间我才会注意到服务的内存失控,并且在运行2周内会出现内存不足异常 我认为这个问题可能与大量没有离开终结队列的对象有关 我已使用Windbg连接到该服务并运行!FinalizationQueue命令并获取: 0:029> !finalizequeue SyncBlocks

我有一个内存泄漏的.NET windows服务应用程序

概述: 该服务通过TCP连接到另一个服务,并将数据写入SQL server数据库。该服务通常在100到300 MB之间运行,这取决于它排队的数据量。通常需要3天以上的时间我才会注意到服务的内存失控,并且在运行2周内会出现内存不足异常

我认为这个问题可能与大量没有离开终结队列的对象有关

我已使用Windbg连接到该服务并运行!FinalizationQueue命令并获取:

0:029> !finalizequeue
SyncBlocks to be cleaned up: 0
Free-Threaded Interfaces to be released: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
generation 0 has 0 finalizable objects (32c69ea4->32c69ea4)
generation 1 has 266 finalizable objects (32c69a7c->32c69ea4)
generation 2 has 23191 finalizable objects (32c53020->32c69a7c)
Ready for finalization 5124616 objects (32c69ea4->33ff66c4)
Statistics for all finalizable objects (including all objects ready for finalization):
      MT    Count    TotalSize Class Name
73e0b3ec        1           16 System.Threading.Gen2GcCallback
73e16648        1           20 Microsoft.Win32.SafeHandles.SafeFileMappingHandle
73e165f8        1           20 Microsoft.Win32.SafeHandles.SafeViewOfFileHandle
73df36f4        1           20 System.Security.Cryptography.SafeKeyHandle
...
73e2b208       36          720 Microsoft.Win32.SafeHandles.SafeWaitHandle
731a7754       33          924 System.Net.SafeFreeCredential_SECURITY
731a2d58       10         1240 System.Diagnostics.PerformanceCounter
59d01074       28         1680 System.Management.ManagementObject
73e2a8c4      175         2100 System.WeakReference
70b0385c       48         6144 System.Data.SqlClient.SqlConnection
731b2e94      201         6432 System.ComponentModel.Container
70b03ef4       86        14104 System.Data.SqlClient.SqlCommand
70b06014      712        14240 System.Data.SqlClient.SNIPacket
73e15b34     1248        24960 System.Threading.ThreadPoolWorkQueueThreadLocals
73e26c74     2238        44760 Microsoft.Win32.SafeHandles.SafeRegistryHandle
**73e2e424     1903        98956 System.Threading.Thread
70b08530      986       295800 System.Data.DataTable
70b08b08    20802      2662656 System.Data.DataColumn
6fab76dc   379139      7582780 System.Transactions.SafeIUnknown
73e30008  4740054    208562376 System.Threading.ReaderWriterLock**
我跑:!ReaderWriterLock上的转储堆并获得:

0:029> !DumpHeap /d -mt 73e30008
    ... Omitted
     Address       MT     Size
    00c51f58 73e30008       44     
    00c5644c 73e30008       44     
    00c5ebc0 73e30008       44     
    00c81420 73e30008       44     
    ... Omitted
    0:029> !Name2EE * System.Threading.ReaderWriterLock
    Module:      739f1000
    Assembly:    mscorlib.dll
    Token:       020004c8
    MethodTable: 73e30008
    EEClass:     73a6ff54
    Name:        System.Threading.ReaderWriterLock
    Module:      00573fbc
    Assembly:    J_ToDatabase.exe
    Module:      00574e0c
    Assembly:    JLibrary.dll
    Module:      72f31000
    Assembly:    System.ServiceProcess.dll
    Module:      72f71000
    Assembly:    System.dll
    Module:      00578034
    Assembly:    JConfigHelper.dll
    Module:      72141000
    Assembly:    System.Windows.Forms.dll
    Module:      72da1000
    Assembly:    System.Drawing.dll
    Module:      0057ac64
    Assembly:    JLib.dll
    Module:      0057ba1c
    Assembly:    J_DB_Deploy.dll
    Module:      0057c8a0
    Assembly:    JModel.dll
    Module:      03571d7c
    Assembly:    JLicense.dll
    Module:      71211000
    Assembly:    System.Xml.dll
    Module:      03574074
    Assembly:    JSecureBase.dll
    Module:      03574804
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      71921000
    Assembly:    System.Configuration.dll
    Module:      71a11000
    Assembly:    System.Core.dll
    Module:      0357539c
    Assembly:    
    Module:      03575c7c
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      59ce1000
    Assembly:    System.Management.dll
    Module:      03577b2c
    Assembly:    Localization.dll
    Module:      03578b6c
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      03579070
    Assembly:    
    Module:      03579840
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      709f1000
    Assembly:    System.Data.dll
    Module:      702f1000
    Assembly:    System.Security.dll
    Module:      70661000
    Assembly:    System.Numerics.dll
    Module:      6faa1000
    Assembly:    System.Transactions.dll
    Module:      6f4e1000
    Assembly:    System.EnterpriseServices.dll
    Module:      6f471000
    Assembly:    System.EnterpriseServices.Wrapper.dll
    Module:      043a2cbc
    Assembly:    JTPlib.dll
    Module:      043a3af8
    Assembly:    JStore.Core.dll
    Module:      043a4920
    Assembly:    SystemEventArgsUtility.dll
    Module:      043a7378
    Assembly:    JMAFLibrary.dll
    Module:      043ace28
    Assembly:    J_A_Library.dll
    Module:      03c0afb8
    Assembly:    DatabaseSharedLibrary.dll
    Module:      03ab1c24
    Assembly:    
    Module:      03ab23f8
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      03ab28f8
    Assembly:    
    Module:      03ab30c8
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      03ab35c8
    Assembly:    
...
**NOTE JSecure showed up like this over 800 times!**
...
    Module:      03ab3d98
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
我试图找出为什么在终结队列中有数百万个ReaderWriterLock,所以我在转储堆中的几个地址上运行了GCRoot并得到:

0:029> !GCRoot 00c5ebc0
    HandleTable:
        005413cc (pinned handle)
        -> 01d133c8 System.Object[]
        -> 00cd2820 System.Diagnostics.TraceSource
        -> 00cd29ac System.Diagnostics.SourceSwitch
        -> 00c71704 System.Diagnostics.SwitchElementsCollection
        -> 00c7177c System.Configuration.ConfigurationValues
        -> 00c5fbec System.Configuration.RuntimeConfigurationRecord
        -> 00c5ebec System.Configuration.RuntimeConfigurationRecord
        -> 00c5eb74 System.Configuration.Internal.InternalConfigRoot
        -> **00c5ebc0** System.Threading.ReaderWriterLock    
    Found 1 unique roots (run '!GCRoot -all' to see all roots). 
我跑了!在锁定地址上执行以下操作:

0:029> !do 00c5ebc0
Name:        System.Threading.ReaderWriterLock
MethodTable: 73e30008
EEClass:     73a6ff54
Size:        44(0x2c) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
73e2c00c  4001890        4        System.IntPtr  1 instance        0 _hWriterEvent
73e2c00c  4001891        8        System.IntPtr  1 instance        0 _hReaderEvent
73e2c00c  4001892        c        System.IntPtr  1 instance        0 _hObjectHandle
73e2f6bc  4001893       10         System.Int32  1 instance        0 _dwState
73e2f6bc  4001894       14         System.Int32  1 instance        0 _dwULockID
73e2f6bc  4001895       18         System.Int32  1 instance        3 _dwLLockID
73e2f6bc  4001896       1c         System.Int32  1 instance        0 _dwWriterID
73e2f6bc  4001897       20         System.Int32  1 instance        3 _dwWriterSeqNum
73e2c494  4001898       24         System.Int16  1 instance        0 _wWriterLevel
我想查看加载了ReaderWriterLock的所有模块,因此我在System.Threading.ReaderWriterLock上运行了Name2EE命令,得到:

0:029> !DumpHeap /d -mt 73e30008
    ... Omitted
     Address       MT     Size
    00c51f58 73e30008       44     
    00c5644c 73e30008       44     
    00c5ebc0 73e30008       44     
    00c81420 73e30008       44     
    ... Omitted
    0:029> !Name2EE * System.Threading.ReaderWriterLock
    Module:      739f1000
    Assembly:    mscorlib.dll
    Token:       020004c8
    MethodTable: 73e30008
    EEClass:     73a6ff54
    Name:        System.Threading.ReaderWriterLock
    Module:      00573fbc
    Assembly:    J_ToDatabase.exe
    Module:      00574e0c
    Assembly:    JLibrary.dll
    Module:      72f31000
    Assembly:    System.ServiceProcess.dll
    Module:      72f71000
    Assembly:    System.dll
    Module:      00578034
    Assembly:    JConfigHelper.dll
    Module:      72141000
    Assembly:    System.Windows.Forms.dll
    Module:      72da1000
    Assembly:    System.Drawing.dll
    Module:      0057ac64
    Assembly:    JLib.dll
    Module:      0057ba1c
    Assembly:    J_DB_Deploy.dll
    Module:      0057c8a0
    Assembly:    JModel.dll
    Module:      03571d7c
    Assembly:    JLicense.dll
    Module:      71211000
    Assembly:    System.Xml.dll
    Module:      03574074
    Assembly:    JSecureBase.dll
    Module:      03574804
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      71921000
    Assembly:    System.Configuration.dll
    Module:      71a11000
    Assembly:    System.Core.dll
    Module:      0357539c
    Assembly:    
    Module:      03575c7c
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      59ce1000
    Assembly:    System.Management.dll
    Module:      03577b2c
    Assembly:    Localization.dll
    Module:      03578b6c
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      03579070
    Assembly:    
    Module:      03579840
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      709f1000
    Assembly:    System.Data.dll
    Module:      702f1000
    Assembly:    System.Security.dll
    Module:      70661000
    Assembly:    System.Numerics.dll
    Module:      6faa1000
    Assembly:    System.Transactions.dll
    Module:      6f4e1000
    Assembly:    System.EnterpriseServices.dll
    Module:      6f471000
    Assembly:    System.EnterpriseServices.Wrapper.dll
    Module:      043a2cbc
    Assembly:    JTPlib.dll
    Module:      043a3af8
    Assembly:    JStore.Core.dll
    Module:      043a4920
    Assembly:    SystemEventArgsUtility.dll
    Module:      043a7378
    Assembly:    JMAFLibrary.dll
    Module:      043ace28
    Assembly:    J_A_Library.dll
    Module:      03c0afb8
    Assembly:    DatabaseSharedLibrary.dll
    Module:      03ab1c24
    Assembly:    
    Module:      03ab23f8
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      03ab28f8
    Assembly:    
    Module:      03ab30c8
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
    Module:      03ab35c8
    Assembly:    
...
**NOTE JSecure showed up like this over 800 times!**
...
    Module:      03ab3d98
    Assembly:    JSecure, Version=17.13.21.82, Culture=neutral
Assembly:JSecure,Version=17.13.21.82,Culture=neutral这似乎是问题的一部分,因为它显示了800多次,我从结果中省略了所有实例,因为它的文本太多

关于JSecure的注意事项,它是一个dll,用于管理我的服务的许可。dll通过加载到我的服务中

System.Reflection.Assembly.Load 
方法,因为安全原因。 我的两个主要问题是

  • 是什么导致JSecure至少被加载了800次
  • 是什么导致数百万System.Threading.ReaderWriterLock留在终结队列中
  • 关于如何进一步追踪内存泄漏的线索

    更新1

    根据评论中的建议,我对终结器线程进行了更多的挖掘。 当我跑的时候!线程,我得到1905个结果,虽然我认为大多数线程也在finalizerqueue中,但只有大约20个活动线程。当我切换到终结器线程并运行kb以获取堆栈跟踪时,我得到:

    0:002> kb
     # ChildEBP RetAddr  Args to Child              
    00 02e2f0e0 75892cc7 000003d4 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
    01 02e2f154 75892c02 000003d4 ffffffff 00000000 KERNELBASE!WaitForSingleObjectEx+0x99
    02 02e2f168 75ff9839 000003d4 ffffffff 0075d59c KERNELBASE!WaitForSingleObject+0x12
    03 (Inline) -------- -------- -------- -------- combase!MTAThreadWaitForCall+0x43 [d:\blue\com\combase\dcomrem\channelb.cxx @ 5657]
    04 02e2f198 7609d524 006e1568 006e5808 02e2f404 combase!MTAThreadDispatchCrossApartmentCall+0x1ed [d:\blue\com\combase\dcomrem\chancont.cxx @ 193]
    05 (Inline) -------- -------- -------- -------- combase!CRpcChannelBuffer::SwitchAptAndDispatchCall+0x33a2 [d:\blue\com\combase\dcomrem\channelb.cxx @ 5052]
    06 02e2f2ec 75f7caea 0075d59c 02e2f404 02e2f3cc combase!CRpcChannelBuffer::SendReceive2+0x62d [d:\blue\com\combase\dcomrem\channelb.cxx @ 4796]
    07 (Inline) -------- -------- -------- -------- combase!ClientCallRetryContext::SendReceiveWithRetry+0x2e [d:\blue\com\combase\dcomrem\callctrl.cxx @ 1090]
    08 (Inline) -------- -------- -------- -------- combase!CAptRpcChnl::SendReceiveInRetryContext+0x81 [d:\blue\com\combase\dcomrem\callctrl.cxx @ 715]
    09 02e2f34c 75fc1789 0075d59c 02e2f404 02e2f3cc combase!DefaultSendReceive+0x9e [d:\blue\com\combase\dcomrem\callctrl.cxx @ 671]
    0a (Inline) -------- -------- -------- -------- combase!CAptRpcChnl::SendReceive+0x38 [d:\blue\com\combase\dcomrem\callctrl.cxx @ 752]
    0b 02e2f3b0 7609a010 0075d59c 02e2f404 02e2f3cc combase!CCtxComChnl::SendReceive+0x248 [d:\blue\com\combase\dcomrem\ctxchnl.cxx @ 735]
    0c 02e2f3d4 77865769 0073be14 02e2f430 77865740 combase!NdrExtpProxySendReceive+0x5c [d:\blue\com\combase\ndr\ndrole\proxy.cxx @ 2017]
    0d 02e2f3ec 778e6c1b ee46341f 0073be14 02e2f850 rpcrt4!NdrpProxySendReceive+0x29
    0e 02e2f818 76099e1e 75f6d8f8 75f72ff0 02e2f850 rpcrt4!NdrClientCall2+0x22b
    0f 02e2f838 75f7c46f 02e2f850 00000008 02e2f8d8 combase!ObjectStublessClient+0x6c [d:\blue\com\combase\ndr\ndrole\i386\stblsclt.cxx @ 215]
    10 02e2f848 75fc1c07 0073be14 02e2f888 006ce0a8 combase!ObjectStubless+0xf [d:\blue\com\combase\ndr\ndrole\i386\stubless.asm @ 171]
    11 02e2f8d8 75fc3024 006ce098 74d08aa9 02e2f99c combase!CObjectContext::InternalContextCallback+0x1e4 [d:\blue\com\combase\dcomrem\context.cxx @ 4428]
    12 02e2f92c 74d086b1 006ce0a8 74d08aa9 02e2f99c combase!CObjectContext::ContextCallback+0xbc [d:\blue\com\combase\dcomrem\context.cxx @ 4332]
    13 02e2fa24 74d08782 74d081d7 02e2fab4 ec1c2444 clr!CtxEntry::EnterContext+0x243
    14 02e2fa5c 74d087c3 74d081d7 02e2fab4 00000000 clr!RCW::EnterContext+0x3a
    15 02e2fa78 74d085a0 006ce150 ec1c2490 752963e8 clr!RCWCleanupList::ReleaseRCWListInCorrectCtx+0xc0
    16 02e2fad4 74cd19c5 ec1c253c 7529562c 00000000 clr!RCWCleanupList::CleanupAllWrappers+0x14d
    17 02e2fb24 74cd1bc8 006ae690 00000001 ec1c24e0 clr!SyncBlockCache::CleanupSyncBlocks+0xd0
    18 02e2fb3c 74cd3ad8 ec1c2550 02e2fc58 02e2fcd0 clr!Thread::DoExtraWorkForFinalizer+0x7f
    19 02e2fb84 74d09b0e 02e2fcd0 006bdcc8 02e2fcd0 clr!WKS::GCHeap::FinalizerThreadWorker+0x232
    1a 02e2fb98 74d09b78 ec1c2224 02e2fcd0 00000000 clr!ManagedThreadBase_DispatchInner+0x67
    1b 02e2fc3c 74d09c45 ec1c2280 00000000 00000040 clr!ManagedThreadBase_DispatchMiddle+0x7e
    1c 02e2fc98 74c852e2 ec1c230c 74c8517c 00000000 clr!ManagedThreadBase_DispatchOuter+0x5b
    1d 02e2fd14 74cd5f91 00000000 00000000 00000000 clr!WKS::GCHeap::FinalizerThreadStart+0x1a0
    1e 02e2fdb4 77917c04 006bd910 77917be0 ee68e49d clr!Thread::intermediateThreadProc+0x4d
    1f 02e2fdc8 77cdab8f 006bd910 ee10b078 00000000 kernel32!BaseThreadInitThunk+0x24
    20 02e2fe10 77cdab5a ffffffff 77cbffdf 00000000 ntdll!__RtlUserThreadStart+0x2f
    21 02e2fe20 00000000 74cd5f48 006bd910 00000000 ntdll!_RtlUserThreadStart+0x1b
    

    您有太多的可终结对象,句号。你需要看看终结器线程在做什么,它可能是死锁的。谢谢,我会用终结器线程的信息更新我的帖子。是的,它是死锁的。一个非常常见的终结器线程死锁场景。它正在尝试完成单元线程COM对象的RCW,但拥有该COM对象的线程不再响应。您何时创建JSecure对象?JSecure是一次性的吗?您是否有任何理由怀疑您正在重复创建这些对象,并且从未处理过它们?我对此进行了测试,并更改了代码,以确保只创建一个在服务生命周期内存在的实例。在这一变化之后,同样的问题仍然存在。