Istilah Garbage Collector bagi para programmer JAVA merupakan istilah yang tidak asing. Saat suatu kode JAVA digunakan, kode tersebut direpresentasikan sebagai bytecode, dan dijalankan dalam suatu environment yang disebut Java Virtual Machine (JVM). Garbage Collector merupakan mekanisme yang terdapat pada JVM untuk mendeteksi objek-objek yang tidak terpakai dan menghapusnya dari memori yang bertujuan untuk memastikan heap memory cukup besar dalam menjalankan aktifitasnya. Kegagalan dalam mengatur Garbage Collector ini akan menghasilkan kejadian Out of Memory atau memory leaks yang berimbas pada sistem mati dengan sendirinya. Dewasa ini sering ditemukan organisasi yang menjalankan kode JAVA dengan mengeyampingkan konfigurasi Garbage Collector. Lantas adakah best practice dalam mengkonfigurasi Garbage Collector pada JAVA ?
Mengenal Lebih dalam Garbage Collector
Dalam C/C++, seorang programmer bertanggung jawab atas pembuatan dan penghancuran objek. Biasanya programmer menyepelekan hal-hal seperti ini. Kelalaian ini menyebabkan pada titik tertentu tidak tersedia memori yang cukup untuk membuat objek baru, dan seluruh program akan berhenti secara tidak normal, menyebabkan OutOfMemoryErrors.
Namun di Java, programmer tidak perlu memperhatikan semua objek yang sudah tidak digunakan lagi. Garbage Collector akan menghancurkan hal-hal ini secara otomatis. Tujuan utama Garbage Collector adalah mengosongkan tumpukan memori dengan menghancurkan objek yang tidak dapat dijangkau. Hal ini dicapai dengan Garbage Collector mengidentifikasikan objek mana yang digunakan dan mana yang tidak, lantas menghapus objek yang tidak terpakai. Objek yang sedang digunakan, atau objek yang direferensikan, berarti terdapat bagian dari program JAVA anda yang masih menggunakan objek tersebut begitu juga sebaliknya. Sehingga memori yang digunakan oleh objek yang tidak digunakan dapat diperoleh kembali.
Macam Garbage Collector (GC)
Dalam perkembangannya terdapat beberapa varian dan algoritma Garbage Collector yang dapat digunakan oleh programmer JAVA yakni :
- Serial GC: Algoritme GC single-thread sederhana yang cocok untuk aplikasi atau sistem kecil dengan kebutuhan memori rendah.
- Parallel GC: Menggunakan banyak thread untuk mempercepat pengumpulan objek tidak terpakai, sehingga lebih efisien untuk aplikasi yang menghasilkan “sampah” dalam jumlah besar.
- G1 (Garbage-First) GC: GC bergaya server yang membagi heap menjadi beberapa wilayah dan melakukan pengumpulan sampah pada sub-kumpulan heap yang lebih kecil untuk meminimalkan jeda dan meningkatkan throughput.
- Epsilon GC: Algoritma GC no-op yang berguna untuk pengujian dan skenario di mana aplikasi menangani manajemen memori secara independen.
- IBM Metronome GC: Algoritme GC real-time eksperimental yang berfokus pada waktu jeda yang dapat diprediksi dan konsisten.
- CMS (Concurrent Mark-Sweep) GC: Menyediakan Garbace Collector berlatensi rendah dengan melakukan sebagian besar pekerjaan pengumpulan secara bersamaan dengan eksekusi aplikasi.
Algoritma Garbage Collector concurrent juga kian berkembang dengan banyak variannya yang telah dioptimasi oleh masing-masing pihak seperti:
- ZGC: Dirancang untuk aplikasi yang memerlukan waktu jeda sangat rendah, ZGC melakukan pengumpulan sampah secara concurrent tanpa gangguan signifikan pada aplikasi.
- Shenandoah GC: Algoritme GC concurrent lainnya, Shenandoah bertujuan untuk mengurangi waktu jeda dengan melakukan pengumpulan sampah secara bersamaan dengan aplikasi.
- Azul C4 GC: Dirancang untuk persyaratan performa tinggi dan latensi rendah, C4 GC menggunakan teknik pengumpulan concurrent dan tanpa jeda.
- SAP Garbage Collector: Algoritme GC concurrent yang dioptimalkan untuk ukuran tumpukan besar dan persyaratan latensi rendah.
Best Practice dalam Mengelola Garbage Collector pada JAVA:
- Konfigurasi GC: Penting untuk melakukan konfigurasi Garbage Collector sesuai dengan kebutuhan aplikasi. Parameter yang bisa dikonfigurasi termasuk: a) ukuran heap, b) threshold untuk aktivasi GC, c) jenis GC yang digunakan, dan lain-lain. Menyesuaikan ukuran heap (Xmx dan Xms) dengan mempertimbangkan beban kerja aplikasi dapat mengoptimalkan kinerja GC. Misal pada konfigurasi berikut -XX:+UseG1GC -Xmx4G -Xms4G berarti :
- -XX:+UseG1GC : Menggunakan algoritma G1 sebagai algoritma Garbage Collector
- -Xmx4G : Mengalokasikan maksimal heap memory sebesar 4 GB
- -Xms4G : Mengalokasikan bahwa dari awal menggunakan seluruh heap memory yakni 4 GB
- Penting untuk digarisbawahi bahwa Garbage Collector saat kondisi tinggi dapat memakan memori yang sama besar dengan heapnya. Lantas konfigurasi ini menggunakan sekitar 8 GB memori untuk menjalankan aplikasi.
- Memantau dan Menganalisis Kinerja GC: Pemantauan secara teratur terhadap kinerja GC menggunakan alat-alat seperti VisualVM, jstat, atau melalui log GC (garbage collection logs) sangat dianjurkan. Hal ini membantu dalam mendeteksi potensi masalah kinerja atau bottleneck yang berkaitan dengan GC.
- Optimasi Kode: Praktik pengkodean yang baik juga berkontribusi pada kinerja GC. Menghindari pembuatan objek yang tidak perlu secara berulang-ulang (object creation), menggunakan pola desain yang efisien, dan meminimalkan penggunaan objek yang banyak di luar heap adalah beberapa contoh praktik yang dapat mengurangi tekanan pada GC. Penting untuk dipahami bahwa bagi Garbage Collector lebih mudah menghapus satu objek sebesar 10 GB, dibandingkan satu juta objek dengan besar 1 KB. Sehingga pengkodean yang baik betul-betul memegang peranan yang besar.
- Periode Uji Coba dan Optimasi: Aplikasi Java sering memerlukan periode uji coba dan optimasi GC untuk mencapai keseimbangan yang optimal antara kinerja, penggunaan memori, dan responsivitas aplikasi. Pengoptimalan ini dapat melibatkan penyesuaian parameter GC, revisi kode, atau bahkan upgrade versi Java untuk memanfaatkan peningkatan GC yang terbaru.