Another way to do this is with the finalizequeue
command provided by SOS. This shows all objects registered for finalization, not just those that are ready for finalization:
0:010> !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 33 finalizable objects (000000001b2b9710->000000001b2b9818)
generation 1 has 2 finalizable objects (000000001b2b9700->000000001b2b9710)
generation 2 has 580 finalizable objects (000000001b2b84e0->000000001b2b9700)
Ready for finalization 0 objects (000000001b2b9818->000000001b2b9818)
Statistics for all finalizable objects (including all objects ready for finalization):
MT Count TotalSize Class Name
000007feebb95cb8 1 24 System.Threading.OverlappedDataCache
000007feebb81168 1 24 System.LocalDataStoreHolder
000007feebb14630 1 24 System.Threading.TimerHolder
000007feebb63a38 1 32 Microsoft.Win32.SafeHandles.SafePEFileHandle
000007feebb5ae38 1 32 Microsoft.Win32.SafeHandles.SafeFileMappingHandle
000007feebb5ada8 1 32 Microsoft.Win32.SafeHandles.SafeViewOfFileHandle
...<snip>...
Total 615 objects
Then you can dump all objects in the generation 1 range of memory (clipping off the end since it won't be inclusive). I only have two in generation 1 here, fortunately:
0:010> dd 000000001b2b9700 000000001b2b9710-4
00000000`1b2b9700 02d51da0 00000000 02d51d50 00000000
Then dump those objects out (this is just the first one):
0:010> !do 02d51da0
Name: System.WeakReference
MethodTable: 000007feebb6cbb0
EEClass: 000007feeb53f1d8
Size: 24(0x18) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
000007feebb6a338 4000688 8 System.IntPtr 1 instance 2128d8 m_handle