زمانی که این بخش از گراف کامل شد Garbage Collector، rootهای بعدی را چک میکند و مجددا اشیا را بررسی میکند. در طول اینکه Garbage Collector از یک شیی به یک شیی دیگر منتقل میشود، اگر سعی کند که یک شیی تکراری را به گراف اضافه کند، Garbage Collector حرکت در آن مسیر را متوقف میکند. این نوع رفتار دو هدف را دنبال میکند: اول اینکه چون Garbage Collector از هیچ شیی دو بار عبور نمیکند راندمان برنامه را به شکل قابل توجهی افزایش میدهد. دوم اینکه هرچقدر هم در برنامه لیستهای پیوندی دایره ای از اشیا موجود باشند ، Garbage Collector در حلقه های بینهایت نمی ماند.
زمانی که تمام rootها بررسی شدند، گراف Garbage Collector محتوی تمام اشیایی است که به نحوی از طریق rootهای برنامه قابل دسترسی می باشند و هر شیی که در گراف نباشد به این معنی است که توسط برنامه قابل دسترسی نیست و یک زباله محسوب میشود. بعد از این Garbage Collector به صورت خطی heap را طی میکند و دنبال بلاکهای پیوسته از زباله های مشخص شده توسط گراف میگردد (که هم اکنون فضای خالی محسوب میشوند). اگر بلاکهای کوچکی پیدا شوند Garbage Collector این بلاکها را به همان حال قبلی رها میکند.
اگر یک بلاک پیوسته وسیع توسط Garbage Collector یافت شد، در این حال، Garbage Collector اشیای غیر زباله را به سمت پایین حافظه heap شیفت میدهد (و این کار با تابع استاندارد memcopy انجام میشود) و به این طریق heap را فشرده میکند. طبیعتا حرکت دادن اشیا به سمت پایین در heap باعث نامعتبر شدن تمام اشاره گرهای موجود برای آن اشیا میشود. به علاوه، اگر شیی محتوی اشاره گری به شیی دیگری بود Garbage Collector مسئول تصحیح این اشاره گرها میشود. بعد از این که این عمل فشرده سازی روی heap انجام شد NextObjPtr به آخرین شیی غیر زباله اشاره میکند. شکل زیر یک managed heap را بعد از اتمام کار Garbage Collector نشان میدهد.