Konuştuklarımızda Java'nın garbage collection mekanizmasını tam anlamak istiyorum. Temel prensipler neler ve performansı nasıl etkiliyor? Bazı durumlarda GC süresinin uzun olduğunu duyuyorum, bunun sebebi ne olabilir?
Java'da garbage collection nasıl çalışır?
👁️ 30 görüntüleme💬 1 cevap❤️ 0 beğeni
1 Cevap
Java'daki garbage collection (GC)'ın nasıl çalıştığını anlamak için öncelikle temeldeki prensiplere odaklanmak gerekiyor. Java, bellek yönetimini otomatik hale getirerek geliştiricilerin elle *new* ile oluşturulan objelerin ömrünü takip etmesini gerektirmez, bunun yerine GC devreye girerek kullanılan nesneleri otomatik temizler. Temel olarak üç tip GC algoritması var: **Genç Nesil (Young Generation) temizleme**, **Yaşlı Nesil (Old Generation) temizleme** ve **Serial/Parallel/Concurrent Mark-Sweep** gibi farklı stratejiler. Özellikle *Genç Nesil* devreye girip çok hızlı çalışır çünkü çoğu nesne kısa ömürlüdür ve "Eden Space" adı verilen alanda toplanır. Eğer bir nesne sürekli kullanılıyorsa "Survivor Spaces" üzerinden *Yaşlı Nesil*'e geçer ve orada toplanır.
Performansa gelince, GC süresinin uzun olması genellikle birden fazla sebebe bağlı olabilir. En sık karşılaştığım durumlar şunlar:
- **Büyük objelerin sürekli oluşturulması** (örneğin, çok sayıda *ArrayList* oluşturup sonra unutmak). Bu, GC'nin sürekli devreye girip temizleme yapmasına sebep olur.
- **Uygun olmayan JVM ayarları**, özellikle `-Xms` ve `-Xmx` değerlerinin çok dar veya çok geniş ayarlanması. Küçük heap belleği sık GC döngülerine, büyük heap belleğiyse uzun duraksamalara yol açabilir.
- **Memory leak'ler** – objelerin gereksiz yere referanslanır bırakılması. Bir kez bile kapatılmayan bağlantıları (JS, veritabanı) unutmak, GC'nin bu objeleri serbest bırakmasını engeller ve sonunda heap dolup `OutOfMemoryError` almanıza sebep olur.
Benchmarklama yaparken VisualVM ya da Eclipse Memory Analyzer (MAT) gibi araçlarla heap dump'ları inceleyip hangi objelerin sürekli kalıp GC'yi tetiklediğini bulabilirsin. Benim deneyimimde, sık GC duraksamaları için en etkili çözümlerden biri, büyük objenin *try-with-resources* kullanarak hemen kapatılması ve gereksiz buffer'ların (örneğin InputStream) kapatılmasıydı. Ayrıca, `-XX:+UseZGC` gibi modern GC algoritmalarını denemek de heap boyutu arttıkça performansı ciddi şekilde iyileştirebiliyor.