Bu kapsamlı Java Sanal Makinesi (JVM) çöp toplama ayarları kılavuzuyla Java uygulamalarınızın performansını ve kaynak kullanımını optimize edin. Farklı çöp toplayıcıları, ayar parametreleri ve küresel uygulamalar için pratik örnekler hakkında bilgi edinin.
Java Sanal Makinesi: Çöp Toplama Ayarlarına Derinlemesine Bir Bakış
Java'nın gücü, Java Sanal Makinesi (JVM) aracılığıyla elde edilen platform bağımsızlığında yatar. JVM'nin kritik bir yönü, öncelikle çöp toplayıcı (GC) tarafından yönetilen otomatik bellek yönetimidir. Özellikle çeşitli iş yükleri ve büyük veri kümeleriyle uğraşan küresel uygulamalar için, GC'yi anlamak ve ayarlamak, optimum uygulama performansı için çok önemlidir. Bu kılavuz, Java uygulamalarınızı optimize etmenize yardımcı olmak için farklı çöp toplayıcıları, ayar parametreleri ve pratik örnekleri kapsayan kapsamlı bir GC ayarı genel bakışı sunar.
Java'da Çöp Toplamayı Anlamak
Çöp toplama, bir program tarafından artık kullanılmayan nesneler tarafından işgal edilen belleği otomatik olarak geri kazanma işlemidir. Bu, bellek sızıntılarını önler ve geliştiricileri C ve C++ gibi dillere kıyasla önemli bir avantaj olan manuel bellek yönetiminden kurtararak geliştirmeyi basitleştirir. JVM'nin GC'si bu kullanılmayan nesneleri belirler ve kaldırır, belleği gelecekteki nesne oluşturma için kullanılabilir hale getirir. Çöp toplayıcısının seçimi ve ayar parametreleri, aşağıdakiler dahil olmak üzere uygulama performansını derinden etkiler:
- Uygulama Duraklamaları: Uygulama iş parçacıklarının GC çalışırken askıya alındığı 'dünyayı durdurma' olayları olarak da bilinen GC duraklamaları. Sık veya uzun duraklamalar, kullanıcı deneyimini önemli ölçüde etkileyebilir.
- Verim: Uygulamanın görevleri işleyebildiği oran. GC, fiili uygulama çalışması için kullanılabilecek CPU kaynaklarının bir bölümünü tüketebilir, böylece verimliliği etkiler.
- Bellek Kullanımı: Uygulamanın mevcut belleği ne kadar verimli kullandığı. Kötü yapılandırılmış GC, aşırı bellek kullanımına ve hatta bellek yetersizliği hatalarına yol açabilir.
- Gecikme Süresi: Uygulamanın bir isteğe yanıt vermesi için geçen süre. GC duraklamaları doğrudan gecikme süresine katkıda bulunur.
JVM'deki Farklı Çöp Toplayıcılar
JVM, her birinin kendine özgü güçlü ve zayıf yönleri olan çeşitli çöp toplayıcılar sunar. Bir çöp toplayıcısının seçimi, uygulamanın gereksinimlerine ve iş yükü özelliklerine bağlıdır. Önemli olanlardan bazılarını inceleyelim:
1. Seri Çöp Toplayıcı
Seri GC, öncelikle tek çekirdekli makinelerde veya çok küçük yığınlara sahip olanlarda çalışan uygulamalar için uygun, tek iş parçacıklı bir toplayıcıdır. En basit toplayıcıdır ve tam GC döngüleri gerçekleştirir. En büyük dezavantajı, uzun 'dünyayı durdurma' duraklamalarıdır ve bu da onu düşük gecikme süresi gerektiren üretim ortamları için uygun hale getirmez.
2. Paralel Çöp Toplayıcı (Verim Toplayıcı)
Verim toplayıcı olarak da bilinen Paralel GC, uygulama verimini en üst düzeye çıkarmayı amaçlar. Minör ve majör çöp toplamayı gerçekleştirmek için birden fazla iş parçacığı kullanır ve bireysel GC döngülerinin süresini azaltır. Toplam verimliliği en üst düzeye çıkarmanın düşük gecikme süresinden daha önemli olduğu, toplu işleme işleri gibi uygulamalar için iyi bir seçimdir.
3. CMS (Eşzamanlı İşaret Süpürme) Çöp Toplayıcı (Kullanımdan Kaldırıldı)
CMS, çöp toplamanın çoğunu uygulama iş parçacıklarıyla eşzamanlı olarak gerçekleştirerek duraklama sürelerini azaltmak için tasarlanmıştır. Eşzamanlı bir işaret-süpürme yaklaşımı kullandı. CMS, Paralel GC'den daha düşük duraklamalar sağlarken, parçalanmadan muzdarip olabilir ve daha yüksek bir CPU yüküne sahipti. CMS, Java 9 itibarıyla kullanımdan kaldırılmıştır ve yeni uygulamalar için artık önerilmemektedir. G1GC ile değiştirildi.
4. G1GC (Garbage-First Çöp Toplayıcı)
G1GC, Java 9'dan beri varsayılan çöp toplayıcıdır ve hem büyük yığın boyutları hem de düşük duraklama süreleri için tasarlanmıştır. Yığını bölgelere ayırır ve en çok çöp dolu bölgeleri toplamaya öncelik verir, dolayısıyla 'Garbage-First' adı. G1GC, verim ve gecikme süresi arasında iyi bir denge sağlar ve bu da onu çok çeşitli uygulamalar için çok yönlü bir seçim haline getirir. Duraklama sürelerini belirtilen bir hedefte (örneğin, 200 milisaniye) tutmayı amaçlar.
5. ZGC (Z Çöp Toplayıcı)
ZGC, Java 11'de tanıtılan (Java 11'de deneysel, Java 15'ten itibaren üretime hazır) düşük gecikmeli bir çöp toplayıcıdır. Yığın boyutundan bağımsız olarak GC duraklama sürelerini 10 milisaniye kadar düşük tutmayı amaçlar. ZGC, uygulama neredeyse kesintisiz çalışırken eşzamanlı olarak çalışır. Yüksek frekanslı alım satım sistemleri veya çevrimiçi oyun platformları gibi son derece düşük gecikme süresi gerektiren uygulamalar için uygundur. ZGC, nesne referanslarını izlemek için renkli işaretçiler kullanır.
6. Shenandoah Çöp Toplayıcı
Shenandoah, Red Hat tarafından geliştirilen düşük duraklama süreli bir çöp toplayıcıdır ve ZGC'ye potansiyel bir alternatiftir. Ayrıca, eşzamanlı çöp toplama gerçekleştirerek çok düşük duraklama sürelerini hedefler. Shenandoah'nun temel farklılaştırıcı özelliği, parçalanmayı azaltmaya yardımcı olabilen yığını eşzamanlı olarak sıkıştırabilmesidir. Shenandoah, OpenJDK ve Java'nın Red Hat dağıtımlarından üretime hazırdır. Düşük duraklama süreleri ve verimlilik özellikleri ile bilinir. Shenandoah, uygulamanın yürütülmesini hiçbir an durdurmama avantajına sahip olan uygulama ile tamamen eşzamanlıdır. Çalışma ek bir iş parçacığı aracılığıyla yapılır.
Temel GC Ayar Parametreleri
Çöp toplamayı ayarlamak, performansı optimize etmek için çeşitli parametrelerin ayarlanmasını içerir. İşte netlik için kategorilere ayrılmış, dikkate alınması gereken bazı kritik parametreler:
1. Yığın Boyutu Yapılandırması
-Xms
(Minimum Yığın Boyutu): Başlangıç yığın boyutunu ayarlar. Bunu-Xmx
ile aynı değere ayarlamak, JVM'nin çalışma zamanında yığını yeniden boyutlandırmasını önlemek için genellikle iyi bir uygulamadır.-Xmx
(Maksimum Yığın Boyutu): Maksimum yığın boyutunu ayarlar. Bu, yapılandırılacak en kritik parametredir. Doğru değeri bulmak deney ve izlemeyi içerir. Daha büyük bir yığın, verimi artırabilir ancak GC'nin daha sıkı çalışması gerekiyorsa duraklama sürelerini artırabilir.-Xmn
(Genç Nesil Boyutu): Genç neslin boyutunu belirtir. Yeni nesneler başlangıçta burada tahsis edilir. Daha büyük bir genç nesil, küçük GC'lerin sıklığını azaltabilir. G1GC için, genç nesil boyutu otomatik olarak yönetilir ancak-XX:G1NewSizePercent
ve-XX:G1MaxNewSizePercent
parametreleri kullanılarak ayarlanabilir.
2. Çöp Toplayıcı Seçimi
-XX:+UseSerialGC
: Seri GC'yi etkinleştirir.-XX:+UseParallelGC
: Paralel GC'yi (verim toplayıcı) etkinleştirir.-XX:+UseG1GC
: G1GC'yi etkinleştirir. Bu, Java 9 ve sonraki sürümler için varsayılandır.-XX:+UseZGC
: ZGC'yi etkinleştirir.-XX:+UseShenandoahGC
: Shenandoah GC'yi etkinleştirir.
3. G1GC'ye Özel Parametreler
-XX:MaxGCPauseMillis=
: G1GC için milisaniye cinsinden hedef maksimum duraklama süresini ayarlar. GC bu hedefe ulaşmaya çalışacaktır, ancak bu bir garanti değildir.-XX:G1HeapRegionSize=
: G1GC için yığın içindeki bölgelerin boyutunu ayarlar. Bölge boyutunu artırmak, potansiyel olarak GC yükünü azaltabilir.-XX:G1NewSizePercent=
: G1GC'de genç nesil için kullanılan yığının minimum yüzdesini ayarlar.-XX:G1MaxNewSizePercent=
: G1GC'de genç nesil için kullanılan yığının maksimum yüzdesini ayarlar.-XX:G1ReservePercent=
: Yeni nesnelerin tahsisi için ayrılan bellek miktarı. Varsayılan değer %10'dur.-XX:G1MixedGCCountTarget=
: Bir döngüdeki karma çöp toplamaların hedef sayısını belirtir.
4. ZGC'ye Özel Parametreler
-XX:ZUncommitDelay=
: ZGC'nin belleği işletim sistemine geri vermeden önce bekleyeceği süre (saniye cinsinden).-XX:ZAllocationSpikeFactor=
: Tahsis oranı için ani artış faktörü. Daha yüksek bir değer, GC'nin çöp toplamak için daha agresif çalışmasına izin verildiğini ve daha fazla CPU döngüsü tüketebileceğini gösterir.
5. Diğer Önemli Parametreler
-XX:+PrintGCDetails
: GC döngüleri, duraklama süreleri ve bellek kullanımı hakkında değerli bilgiler sağlayan ayrıntılı GC günlüğünü etkinleştirir. Bu, GC davranışını analiz etmek için çok önemlidir.-XX:+PrintGCTimeStamps
: GC günlük çıktısına zaman damgaları ekler.-XX:+UseStringDeduplication
(Java 8u20 ve sonraki sürümler, G1GC): Yığındaki aynı dizelerin mükerrerlerini kaldırarak bellek kullanımını azaltır.-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
: Geçerli JDK'de açık GC çağrılarının kullanımını etkinleştirir veya devre dışı bırakır. Bu, üretim ortamında performans düşüşünü önlemek için kullanışlıdır.-XX:+HeapDumpOnOutOfMemoryError
: Bir OutOfMemoryError oluştuğunda, bellek kullanımının ayrıntılı analizi ve bellek sızıntılarının tanımlanması için bir yığın dökümü oluşturur.-XX:HeapDumpPath=
: Yığın dökümü dosyasının yazılması gereken konumu belirtir.
Pratik GC Ayar Örnekleri
Farklı senaryolar için bazı pratik örneklere göz atalım. Bunların başlangıç noktaları olduğunu ve uygulamanızın belirli özelliklerine göre deney ve izleme gerektirdiğini unutmayın. Uygun bir temel oluşturmak için uygulamaları izlemek önemlidir. Ayrıca, sonuçlar donanıma bağlı olarak değişebilir.
1. Toplu İşleme Uygulaması (Verime Odaklı)
Toplu işleme uygulamaları için birincil hedef genellikle verimi en üst düzeye çıkarmaktır. Düşük gecikme süresi o kadar kritik değildir. Paralel GC genellikle iyi bir seçimdir.
java -Xms4g -Xmx4g -XX:+UseParallelGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -jar mybatchapp.jar
Bu örnekte, minimum ve maksimum yığın boyutunu 4 GB olarak ayarlıyoruz, Paralel GC'yi etkinleştiriyoruz ve ayrıntılı GC günlüğünü etkinleştiriyoruz.
2. Web Uygulaması (Gecikmeye Duyarlı)
Web uygulamaları için, iyi bir kullanıcı deneyimi için düşük gecikme süresi çok önemlidir. G1GC veya ZGC (veya Shenandoah) genellikle tercih edilir.
G1GC Kullanımı:
java -Xms8g -Xmx8g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -jar mywebapp.jar
Bu yapılandırma, minimum ve maksimum yığın boyutunu 8GB olarak ayarlar, G1GC'yi etkinleştirir ve hedef maksimum duraklama süresini 200 milisaniyeye ayarlar. Performans gereksinimlerinize göre MaxGCPauseMillis
değerini ayarlayın.
ZGC Kullanımı (Java 11+ gerektirir):
java -Xms8g -Xmx8g -XX:+UseZGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -jar mywebapp.jar
Bu örnek, benzer bir yığın yapılandırmasıyla ZGC'yi etkinleştirir. ZGC çok düşük gecikme süresi için tasarlandığından, genellikle bir duraklama süresi hedefi yapılandırmanıza gerek yoktur. Belirli senaryolar için parametreler ekleyebilirsiniz; örneğin, tahsis oranı sorunlarınız varsa, -XX:ZAllocationSpikeFactor=2
deneyebilirsiniz
3. Yüksek Frekanslı Alım Satım Sistemi (Son Derece Düşük Gecikme Süresi)
Yüksek frekanslı alım satım sistemleri için, son derece düşük gecikme süresi en önemli husustur. Uygulama ile uyumlu olması koşuluyla, ZGC ideal bir seçimdir. Java 8 kullanıyorsanız veya uyumluluk sorunlarınız varsa, Shenandoah'yu düşünün.
java -Xms16g -Xmx16g -XX:+UseZGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -jar mytradingapp.jar
Web uygulaması örneğine benzer şekilde, yığın boyutunu ayarlıyoruz ve ZGC'yi etkinleştiriyoruz. İş yüküne bağlı olarak ZGC'ye özel parametreleri daha fazla ayarlamayı düşünün.
4. Büyük Veri Kümelerine Sahip Uygulamalar
Çok büyük veri kümeleriyle ilgilenen uygulamalar için dikkatli düşünmek gerekir. Daha büyük bir yığın boyutu gerekebilir ve izleme daha da önemlidir. Veriler, veri kümesi küçükse ve boyut genç nesile yakınsa Genç nesilde de önbelleğe alınabilir.
Aşağıdaki noktaları göz önünde bulundurun:
- Nesne Tahsis Oranı: Uygulamanız çok sayıda kısa ömürlü nesne oluşturuyorsa, genç nesil yeterli olabilir.
- Nesne Ömrü: Nesneler daha uzun süre yaşamaya eğilimliyse, genç nesilden eski nesile yükselme oranını izlemeniz gerekir.
- Bellek Ayak İzi: Uygulama belleğe bağlıysa ve OutOfMemoryError özel durumlarıyla karşılaşıyorsanız, nesnenin boyutunu azaltmak veya onları kısa ömürlü yapmak sorunu çözebilir.
Büyük bir veri kümesi için, genç nesil ve eski nesil oranı önemlidir. Düşük duraklama süreleri elde etmek için aşağıdaki örneği göz önünde bulundurun:
java -Xms32g -Xmx32g -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1NewSizePercent=20 -XX:G1MaxNewSizePercent=30 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -jar mydatasetapp.jar
Bu örnek, daha büyük bir yığın (32GB) ayarlar ve daha düşük bir hedef duraklama süresi ve ayarlanmış bir genç nesil boyutu ile G1GC'yi ince ayarlar. Parametreleri buna göre ayarlayın.
İzleme ve Analiz
GC'yi ayarlamak tek seferlik bir çaba değildir; dikkatli izleme ve analiz gerektiren yinelenebilir bir süreçtir. İzlemeye nasıl yaklaşacağınız aşağıda açıklanmıştır:
1. GC Günlüğü
-XX:+PrintGCDetails
, -XX:+PrintGCTimeStamps
ve -Xloggc:
gibi parametreleri kullanarak ayrıntılı GC günlüğünü etkinleştirin. GC davranışını, duraklama süreleri, GC döngülerinin sıklığı ve bellek kullanımı kalıpları dahil olmak üzere anlamak için günlük dosyalarını analiz edin. GC günlüklerini görselleştirmek ve analiz etmek için GCViewer veya GCeasy gibi araçları kullanmayı düşünün.
2. Uygulama Performans İzleme (APM) Araçları
CPU kullanımı, bellek kullanımı, yanıt süreleri ve hata oranları dahil olmak üzere uygulama performansını izlemek için APM araçlarını (örneğin, Datadog, New Relic, AppDynamics) kullanın. Bu araçlar, GC ile ilgili darboğazları belirlemenize ve uygulama davranışı hakkında bilgi edinmenize yardımcı olabilir. Piyasadaki Prometheus ve Grafana gibi araçlar da gerçek zamanlı performans bilgileri görmek için kullanılabilir.
3. Yığın Dökümleri
OutOfMemoryError oluştuğunda yığın dökümleri (-XX:+HeapDumpOnOutOfMemoryError
ve -XX:HeapDumpPath=
kullanarak) alın. Bellek sızıntılarını belirlemek ve nesne tahsis kalıplarını anlamak için Eclipse MAT (Memory Analyzer Tool) gibi araçları kullanarak yığın dökümlerini analiz edin. Yığın dökümleri, uygulamanın belirli bir andaki bellek kullanımının bir anlık görüntüsünü sağlar.
4. Profilleme
Kodunuzdaki performans darboğazlarını belirlemek için Java profil oluşturma araçlarını (örneğin, JProfiler, YourKit) kullanın. Bu araçlar, nesne oluşturma, yöntem çağrıları ve CPU kullanımı hakkında bilgi sağlayabilir ve bu da dolaylı olarak uygulamanın kodunu optimize ederek GC'yi ayarlamanıza yardımcı olabilir.
GC Ayarı için En İyi Uygulamalar
- Varsayılanlarla Başlayın: JVM varsayılanları genellikle iyi bir başlangıç noktasıdır. Erken ayarlamayın.
- Uygulamanızı Anlayın: Uygulamanızın iş yükünü, nesne tahsis desenlerini ve bellek kullanım özelliklerini bilin.
- Üretim Benzeri Ortamlarda Test Edin: Performans etkisini doğru bir şekilde değerlendirmek için GC yapılandırmalarını üretim ortamınıza benzeyen ortamlarda test edin.
- Sürekli İzleyin: GC davranışını ve uygulama performansını sürekli olarak izleyin. Gözlemlenen sonuçlara göre ayarlama parametrelerini gerektiği gibi ayarlayın.
- Değişkenleri İzole Edin: Ayarlama yaparken, her bir değişikliğin etkisini anlamak için bir seferde yalnızca bir parametreyi değiştirin.
- Erken Optimizasyondan Kaçının: Katı veri ve analiz olmadan algılanan bir sorun için optimize etmeyin.
- Kod Optimizasyonunu Düşünün: Nesne oluşturmayı ve çöp toplama yükünü azaltmak için kodunuzu optimize edin. Örneğin, mümkün olduğunda nesneleri yeniden kullanın.
- Güncel Kalın: GC teknolojisindeki ve JVM güncellemelerindeki en son gelişmelerden haberdar olun. Yeni JVM sürümleri genellikle çöp toplamada iyileştirmeler içerir.
- Ayarınızı Belgeleyin: GC yapılandırmasını, seçimlerinizin gerekçesini ve performans sonuçlarını belgeleyin. Bu, gelecekteki bakım ve sorun giderme işlemlerine yardımcı olur.
Sonuç
Çöp toplama ayarı, Java uygulama performansı optimizasyonunun kritik bir yönüdür. Farklı çöp toplayıcıları, ayarlama parametrelerini ve izleme tekniklerini anlayarak, uygulamalarınızı belirli performans gereksinimlerini karşılayacak şekilde etkili bir şekilde optimize edebilirsiniz. GC ayarının yinelenen bir süreç olduğunu ve optimum sonuçlar elde etmek için sürekli izleme ve analiz gerektirdiğini unutmayın. Varsayılanlarla başlayın, uygulamanızı anlayın ve ihtiyaçlarınıza en uygun olanı bulmak için farklı yapılandırmalar deneyin. Doğru yapılandırma ve izleme ile, küresel erişiminiz ne olursa olsun, Java uygulamalarınızın verimli ve güvenilir bir şekilde çalışmasını sağlayabilirsiniz.