VDS (Sanal Özel Sunucu) üzerinde çalışan Java uygulamaları, zaman içinde giderek daha fazla bellek tüketmeye başlayabiliyor ve sonunda java.lang.OutOfMemoryError hatası vererek çöküyor. Başlangıçta uygulama sorunsuz çalışıyorken, günler veya haftalar sonra beklenmedik şekilde kapanmalar yaşanıyorsa, neredeyse kesin olarak bellek sızıntısı (memory leak) sorunu vardır. Bu sorunu tanımak, kökünü bulmak ve çözmek için neleri kontrol etmeniz gerektiğini detaylı şekilde açıklayalım.
Bellek Sızıntısı Nedir ve Java'da Neden Oluşur?
Java'da bellek otomatik olarak garbage collector tarafından yönetilir. Ancak uygulama kodu, artık kullanılmayan nesneleri bellekte tutmaya devam ederse, garbage collector bu nesneleri temizleyemez. Zamanla bu "ölü" nesneler yığılır ve kullanılabilir bellek sınırına ulaşır. VDS ortamında RAM sabit olduğu için, sızıntının etkisi daha hızlı görülür. Tipik nedenler:
- Statik koleksiyonlar: HashMap, List gibi yapıların statik olarak tanımlanması ve içlerine hiç kaldırılmayan veri eklenmesi
- Kapalı kaynaklar: veritabanı bağlantısı, dosya stream'i ya da network socket'i açılıp kapatılmadığı durumlar
- Event listener'lar: Kayıtlı listener'ların kaldırılmadan eklenmesi
- Thread'ler: Sonlandırılmayan background thread'leri ve özellikle ThreadLocal değişkenleri
- Cache mekanizmaları: Sınırsız cache implementasyonları
VDS'de Bellek Kullanımını Gerçek Zamanlı İzleme
Sorunu çözmeden önce, belleğin nasıl arttığını gözlemlemek önemlidir. Java'nın kendi araçlarını kullanarak bellek profili alabilirsiniz.
jps komutuyla çalışan Java prosesinin PID'sini öğrenin:
jps -l
Ardından jstat ile garbage collection istatistiklerini takip edin:
jstat -gc -h10 <PID> 1000
Bu komut her saniye GC istatistiklerini yazdırır. OU (Old Generation kullanımı) sütunu sürekli artıyorsa ve garbage collection ile azalmıyorsa, bellek sızıntısı vardır. Ayrıca VDS'de basit bir script ile sistem belleğini de kontrol edebilirsiniz:
watch -n 5 'free -h && echo "---" && ps aux | grep java'
Heap Dump Almak ve Analiz Etmek
Bellek sızıntısının tam yerini bulmak için, uygulama çökmeden hemen önce heap dump almalısınız. VDS'de yeterli disk alanı varsa:
jmap -dump:live,format=b,file=heap.bin <PID>
Bu komut, Java procesinin bellek görüntüsünü heap.bin dosyasına kaydeder. Daha sonra lokal ortamınızda Eclipse Memory Analyzer Tool (MAT) veya JProfiler gibi araçlarla analiz edebilirsiniz. MAT, hangi sınıfların en fazla bellek kullandığını, ne kadar nesnenin oluşturulduğunu ve bunların referans zincirini gösterir.
Ayrıca VDS'de yer kısıtlıysa, -XX:+HeapDumpOnOutOfMemoryError parametresiyle otomatik dump alabilirsiniz. Bunu Java başlangıç parametrelerine ekleyin:
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp MyApplication
Kod Seviyesinde Sızıntı Kaynaklarını Tanımlamak
Heap dump analizi sonucu şüpheli sınıflar belirlediyseniz, kodunuzu gözden geçirin. Sık karşılaşılan hatalar:
- Statik cache:
private static Map<String, Object> cache = new HashMap<>();– eklenen veriler hiç silinmiyor - Kapalı stream:
FileInputStream fis = new FileInputStream("file.txt"); byte[] data = fis.readAllBytes();– stream kapatılmadı - Listener kaydı: Componentin constructor'unda listener eklenip destroy/cleanup metodu yazılmıyor
Bu sorunları çözmek için try-with-resources kullanın:
try (FileInputStream fis = new FileInputStream("file.txt")) { byte[] data = fis.readAllBytes(); }
Statik koleksiyonlar yerine TimeBasedEvictionPolicy veya CacheBuilder (Guava kütüphanesi) gibi çözümler tercih edin.
Heap Size Ayarı ve Graceful Shutdown
Kısa vadede, VDS'deki heap boyutunu optimize edebilirsiniz. -Xms (başlangıç) ve -Xmx (maksimum) parametreleriyle kontrol edin:
java -Xms512m -Xmx2g MyApplication
Ancak heap boyutunu artırmak sızıntıyı çözmez, sadece çöküş zamanını geciktirir. Kök neden mutlaka bulunmalıdır. Ayrıca production ortamında graceful shutdown mekanizması kurun. Uygulama OutOfMemory hatası almadan hemen önce sistem tarafından öldürülmüş olabilir. Bunu önlemek için monitoring + otomatik restart yapılandırın.
Monitoring ve Otomatik Uyarılar Kurulumu
VDS'de uygulamayı sağlıklı tutmak için, bellek kullanımını sürekli izlemeli ve eşik değeri aştığında uyarı almalısınız. Micrometer veya Prometheus client'ini uygulamaya entegre edip, Grafana dashboard'u oluşturabilirsiniz. Ayrıca systemd service file'ında MemoryLimit ve Restart direktiflerini ayarlayarak, OOM durumunda otomatik yeniden başlatma sağlayın.
Uzun Vadeli Çözüm ve Profiling
Bellek sızıntısı, genellikle tasarım hatasının göstergesidir. Sızıntı çözüldükten sonra, production ortamında düzenli olarak profiling yapın. JProfiler, YourKit veya açık kaynak Async Profiler gibi araçlarla CPU ve bellek kullanımını takip edin. Bu, gelecekteki sorunları erken aşamada yakalamaya yardımcı olur.
VDS ortamında çalışan Java uygulamalarının stabil kalması, doğru bellek yönetimi ve proaktif monitoring ile başlar. Bogahost'un yönetimli VDS hizmetleri ile, sistem kaynak izleme ve oto-scale imkanları sayesinde, bu tür sorunlara hızlı müdahale edebilir ve uygulamanızın her zaman sağlıklı kalmasını sağlayabilirsiniz.
Yorumlar (0)
Henüz yorum yapılmamış. İlk yorumu siz yapın!
Yorum Yap