{"id":23188,"date":"2010-11-15T15:38:00","date_gmt":"2010-11-15T15:38:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/maoni\/2010\/11\/15\/finalization-uncovered\/"},"modified":"2021-10-04T13:04:23","modified_gmt":"2021-10-04T20:04:23","slug":"finalization-uncovered","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/finalization-uncovered\/","title":{"rendered":"Finalization Uncovered"},"content":{"rendered":"<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">I&rsquo;ve talked about finalization before but based on seeing questions related to it it appears that it deserves some clarification.<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">&nbsp;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">First of all, finalization is a mechanism we provide in the CLR wheras Dispose is a programming pattern. See <a href=\"http:\/\/blogs.msdn.com\/b\/maoni\/archive\/2004\/11\/04\/252697.aspx\">Clearing up some confusion over finalization and other areas in GC<\/a> for an explanation why we provide finalization. Inside of the GC, it&rsquo;s completely not aware of Dispose. People often call GC.SuppressFinalize in their Dispose implementation but that&rsquo;s just a choice they make when they write code. I will explain exactly what GC.SuppressFinalize does in a bit. Oh and I am not the owner of the &ldquo;Dispose pattern&rdquo; <\/span><span style=\"font-size: 9pt;font-family: Wingdings\"><span>J<\/span><\/span><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\"> <\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">&nbsp;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">So what happens when you allocate an object with a finalizer? GC&rsquo;s allocator will get called and it&rsquo;s told this object is finalizable. So if GC can successfully allocate this object it will then record that this is a finalizable object. GC maintains a list to record finalizable objects so a new object will be in the gen0 part of that list. Recording just means writing the object address X to an entry in the gen0 part.<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">&nbsp;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">When GC promotes a finalizable object to another generation, it&rsquo;ll move its address to the part of the list for that generation. Of course when the object is compacted we also need to update the entry in the finalize list with the new address.<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">&nbsp;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">When GC finishes marking objects, ie, it has determined which ones should be live, it will look at the list for the generation it&rsquo;s collecting see if those objects are dead. For the dead ones it will then promote that object and move the address to the part of the list that&rsquo;s for &ldquo;ready for finalization&rdquo; objects. If any of such objects are found, GC will signal to the finalizer thread that there&rsquo;s work to do.<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">&nbsp;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">When the managed threads are restarted after GC is done, since the finalizer thread is also a managed thread, it also gets restarted and starts to do its work &ndash; running finalizers. It does this by asking for the entries in the &ldquo;ready for finalization&rdquo; part of the list. Those entries are removed from the list as the objects&rsquo; finalizers are run.<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">&nbsp;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">If you do a !finalizequeue you will see output like this:<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\"><\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\">\n<p><span style=\"font-size: 9pt;color: #0070c0;font-family: 'Verdana','sans-serif'\" lang=\"EN-IN\"><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">0:015&gt; !finalizequeue<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">SyncBlocks to be cleaned up: 0<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">MTA Interfaces to be released: 0<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">STA Interfaces to be released: 0<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">Heap 0<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 0 has 971 finalizable objects (000000000e31b958-&gt;000000000e31d7b0)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 1 has 346 finalizable objects (000000000e31ae88-&gt;000000000e31b958)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 2 has 139 finalizable objects (000000000e31aa30-&gt;000000000e31ae88)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">Ready for finalization 0 objects (000000000e31d7b0-&gt;000000000e31d7b0)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">Heap 1<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 0 has <span>2686<\/span> finalizable objects (000000000d41aa10-&gt;000000000d41fe00)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 1 has 473 finalizable objects (000000000d419b48-&gt;000000000d41aa10)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 2 has 129 finalizable objects (000000000d419740-&gt;000000000d419b48)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">Ready for finalization 0 objects (000000000d41fe00-&gt;000000000d41fe00)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">Heap 2<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 0 has 319 finalizable objects (000000000d298298-&gt;000000000d298c90)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 1 has 302 finalizable objects (000000000d297928-&gt;000000000d298298)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 2 has 241 finalizable objects (000000000d2971a0-&gt;000000000d297928)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">Ready for finalization 0 objects (000000000d298c90-&gt;000000000d298c90)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">Heap 3<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 0 has 147 finalizable objects (000000000c982998-&gt;000000000c982e30)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 1 has 432 finalizable objects (000000000c981c18-&gt;000000000c982998)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">generation 2 has 147 finalizable objects (000000000c981780-&gt;000000000c981c18)<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 8pt;color: #0070c0;font-family: 'Lucida Console'\" lang=\"EN-IN\">Ready for finalization 0 objects (000000000c982e30-&gt;000000000c982e30)&nbsp;<\/span><\/p>\n<p><\/span><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\" lang=\"EN-IN\">&nbsp;<\/span><\/p>\n<\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">As you can see, there are &ldquo;Finalizable&rdquo; objects and &ldquo;Ready for finalization&rdquo; objects, as we talked about above.<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">&nbsp;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">It&rsquo;s very common to see 0 &ldquo;Ready for finalization&rdquo; objects. Why? Because the finalizer thread runs at THREAD_PRIORITY_HIGHEST. As soon as managed threads are resumed it&rsquo;s the first to run unless you have other threads of the same or higher priority. Finalizers usually do very little work so it shouldn&rsquo;t be long before the finalizers are run. If there&rsquo;s another GC happening (other threads can still run and allocate if you have more than 1 CPU), if there are still &ldquo;Ready for finalization&rdquo; entries, we need to make sure those objects are promoted.<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">&nbsp;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">So what happens when you call GC.SuppressFinalize on an object? It just sets a bit for this object that tells the GC to not do the operations it would do for a finalizable object it finds dead, in other words, when GC scans the finalizable objects when it sees that bit is set, it will treat it as if it was not a finalizable object (so the object will be considered completely dead at this point and we will no longer remember it in our &ldquo;Finalizable&rdquo; portion of the list).<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">&nbsp;<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: 9pt;font-family: 'Verdana','sans-serif'\">When you call GC.ReRegisterForFinalize we will check to see if that bit is set, if it&rsquo;s we simply clear it. Otherwise we will ask GC to insert it in the &ldquo;Finalizable&rdquo; portion of the list.<\/span><\/p>\n<p style=\"margin: 0in 0in 2pt\" class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">&nbsp;<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&rsquo;ve talked about finalization before but based on seeing questions related to it it appears that it deserves some clarification. &nbsp; First of all, finalization is a mechanism we provide in the CLR wheras Dispose is a programming pattern. See Clearing up some confusion over finalization and other areas in GC for an explanation why [&hellip;]<\/p>\n","protected":false},"author":3542,"featured_media":58792,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685],"tags":[3011],"class_list":["post-23188","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","tag-maoniposts"],"acf":[],"blog_post_summary":"<p>I&rsquo;ve talked about finalization before but based on seeing questions related to it it appears that it deserves some clarification. &nbsp; First of all, finalization is a mechanism we provide in the CLR wheras Dispose is a programming pattern. See Clearing up some confusion over finalization and other areas in GC for an explanation why [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23188","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/3542"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=23188"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23188\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=23188"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=23188"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=23188"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}