Finalization Queue or F-Reachable Queue? Find Out with SOS
It’s 2012, so time for another post related to finalization. This so-often-abused CLR feature has popped up here in the past. A quick recap:
This time, we’ll see how to determine whether a particular object is in the finalization queue (which means it hasn’t been scheduled for finalization yet) or in the f-reachable queue (which means it’s waiting for the finalizer thread to run its finalizer).
Let’s fire up our trusty WinDbg and SOS and look at some heap objects:
0:003> !dumpheap -stat
...snipped…
000007ff00023b78 1340 32160 MemoryLeak.Schedule
000007ff00023aa0 1340 32160 MemoryLeak.Employee
000007fef5ff7b08 435 44400 System.String
000007fef5fe58f8 310 67120 System.Object[]
00000000005387f0 577 2680608 Free
000007fef5fffb48 1345 13432600 System.Byte[]
Total 6231 objects
Okay, what are these schedules, employees, and byte arrays running around?
0:003> .foreach (obj {!dumpheap -mt 000007fef5fffb48 -short}) {!gcroot obj; .echo -----}
…edited for clarity…
Finalizer queue:Root:000000002a021a8(MemoryLeak.Employee)->
0000000002a021c0(MemoryLeak.Schedule)->
0000000002a021d8(System.Byte[])
-----
Finalizer queue:Root:000000002a07058(MemoryLeak.Employee)->
0000000002a07070(MemoryLeak.Schedule)->
0000000002a07088(System.Byte[])
-----
Finalizer queue:Root:000000002a0bf08(MemoryLeak.Employee)->
0000000002a0bf20(MemoryLeak.Schedule)->
0000000002a0bf38(System.Byte[])
…many more of these snipped…
Now, are these Employee objects rooted at the finalization queue or the f-reachable queue? Unfortunately, !gcroot does not tell. However, !FinalizeQueue shows the queue statistics:
0:003> !FinalizeQueue
SyncBlocks to be cleaned up: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
----------------------------------
generation 0 has 370 finalizable objects
(0000000000d29030->0000000000d29bc0)
generation 1 has 4 finalizable objects
(0000000000d29010->0000000000d29030)
generation 2 has 8 finalizable objects
(0000000000d28fd0->0000000000d29010)
Ready for finalization 571 objects
(0000000000d29bc0->0000000000d2ad98)
Statistics:
…snipped…
Note the information on finalizable objects vs. objects that are ready for finalization. The former are in the finalization queue, the latter are in the f-reachable queue.
But now suppose that you have an individual object and you want to determine whether it’s in the finalization queue or the f-reachable queue. All you need to do is check in which array it is contained by searching memory with the s command:
0:003> s -q 0000000000d29bc0 0000000000d2ad98 0000000002a0bf08
00000000`00d29da8 00000000`02a0bf08 00000000`02a10db8
0:003> s -q 0000000000d28fd0 0000000000d29bc0 0000000002a0bf08
Okay, so 0000000002a0bf08 is in the f-reachable queue, waiting for the finalizer thread.
I am posting short updates and links on Twitter as well as on this blog. You can follow me: @goldshtn This blog post was also cross-posted to CodeProject.