Kita telah mengalokasikan objek dan melihat rujukan menentukan usianya; kini saatnya bertemu pihak yang membersihkan heap. Garbage collector (GC) adalah layanan runtime yang menelusuri objek yang masih dicakup rujukan, lalu mengklaim kembali memori objek yang tidak lagi dicakup rujukan mana pun. Kita sebagai programmer tidak memanggil GC secara langsung dalam alur normal; GC menentukan waktunya sendiri. Bab ini memberi gambaran pengantar, sedangkan section Garbage Collection setelah section ini membedah mekanismenya secara mendalam.

Cara GC Mengenali Objek yang Tidak Dipakai #

GC memulai pekerjaannya dari kumpulan root, yaitu rujukan yang selalu dianggap terpakai: variabel lokal method yang sedang berjalan, field static, dan register prosesor. Dari root, GC menelusuri rujukan berantai hingga seluruh objek yang masih terpakai tertandai. Objek yang tidak tertandai tidak punya jalur dari root, sehingga memorinya boleh diklaim kembali. Pemrogram tidak perlu menandai apa pun; penelusuran sepenuhnya otomatis.

Contoh: Mengamati Satu Siklus GC #

csharp
int gen0Sebelum = GC.CollectionCount(0);
int gen2Sebelum = GC.CollectionCount(2);

GC.Collect();

Console.WriteLine($"Gen0 bertambah: {GC.CollectionCount(0) - gen0Sebelum} kali");
Console.WriteLine($"Gen2 bertambah: {GC.CollectionCount(2) - gen2Sebelum} kali");
Console.WriteLine($"Generasi tertinggi: {GC.MaxGeneration}");

Output yang Dihasilkan:

text
Gen0 bertambah: 1 kali
Gen2 bertambah: 1 kali
Generasi tertinggi: 2

Mari kita bedah baris demi baris:

  1. GC.CollectionCount(0): API ini melaporkan berapa kali generasi 0 telah dikumpulkan sejak proses dimulai. Kita membaca nilai awal agar bisa menghitung selisih.
  2. GC.Collect(): pemanggilan eksplisit yang memaksa satu siklus GC penuh. Pada aplikasi nyata, GC berjalan sendiri saat memori generasi 0 habis.
  3. Selisih gen0 dan gen2: keduanya bertambah satu karena satu siklus penuh mencakup seluruh generasi. Ini bukti bahwa GC.Collect() tanpa parameter menyapu semua generasi.
  4. GC.MaxGeneration: hasil 2 menunjukkan runtime .NET memakai tiga generasi, yaitu 0, 1, dan 2.

Batas Tanggung Jawab GC #

GC hanya mengelola memori managed heap. Koneksi database, handle file, dan memori yang dipesan lewat kode native berada di luar jangkauannya, sehingga resource semacam itu membutuhkan pola IDisposable yang dibahas pada section Resource Management. GC juga tidak menjanjikan momen pengklaiman yang pasti; ia bekerja saat dibutuhkan, bukan seketika objek kehilangan rujukan.