Java Sanal Makinesi - Nesil GC'ler

Çoğu JVM, yığını üç nesle böler - the young generation (YG), the old generation (OG) and permanent generation (also called tenured generation). Böyle düşünmenin arkasındaki sebepler nelerdir?

Ampirik çalışmalar, yaratılan nesnelerin çoğunun çok kısa ömürlü olduğunu göstermiştir -

Kaynak

https://www.oracle.com

Gördüğünüz gibi, zamanla daha fazla nesne tahsis edildikçe, hayatta kalan bayt sayısı (genel olarak) azalır. Java nesneleri yüksek ölüm oranına sahiptir.

Basit bir örneğe bakacağız. Java'daki String sınıfı değişmezdir. Bu, bir String nesnesinin içeriğini her değiştirmeniz gerektiğinde, tamamen yeni bir nesne oluşturmanız gerektiği anlamına gelir. Aşağıdaki kodda gösterildiği gibi bir döngüde dizide 1000 kez değişiklik yaptığınızı varsayalım -

String str = “G11 GC”;

for(int i = 0 ; i < 1000; i++) {
   str = str + String.valueOf(i);
}

Her döngüde, yeni bir dizgi nesnesi yaratırız ve önceki yineleme sırasında oluşturulan dizge işe yaramaz hale gelir (yani, herhangi bir referans tarafından referans alınmaz). Bu nesnenin T ömrü yalnızca bir yinelemeydi - GC tarafından hiçbir zaman toplanmayacaklar. Bu tür kısa ömürlü nesneler, yığının genç nesil alanında tutulur. Genç nesilden nesnelerin toplanma sürecine küçük çöp toplama adı verilir ve her zaman bir 'dünyayı durdur' duraklamasına neden olur.

Genç nesil doldukça, GC küçük bir çöp toplama işlemi yapar. Ölü nesneler atılır ve canlı nesneler eski nesle taşınır. Bu işlem sırasında uygulama konuları durur.

Burada böyle bir nesil tasarımın sunduğu avantajları görebiliriz. Genç nesil, yığının yalnızca küçük bir parçasıdır ve hızla doldurulur. Ancak işlemek, tüm yığını işlemek için geçen süreden çok daha az zaman alır. Dolayısıyla, bu durumda 'dünyayı durdur' duraklamaları, daha sık olmakla birlikte çok daha kısadır. Daha sık olsalar bile, her zaman daha uzun duraklamalar yerine daha kısa duraklamaları hedeflemeliyiz. Bunu, bu eğitimin sonraki bölümlerinde ayrıntılı olarak tartışacağız.

Genç nesil iki alana bölünmüştür - eden and survivor space. Eden koleksiyonu sırasında hayatta kalan nesneler hayatta kalan alana, hayatta kalanlar ise eski nesile taşınır. Genç nesil toplanırken sıkıştırılır.

Nesneler eski nesle taşınırken, sonunda dolar ve toplanıp sıkıştırılması gerekir. Farklı algoritmalar buna farklı yaklaşımlar getirir. Bazıları uygulama iş parçacığını durdurur (eski nesil genç nesile kıyasla oldukça büyük olduğu için uzun bir 'dünyayı durdur' 'duraklamasına yol açar), bazıları ise uygulama iş parçacığı çalışmaya devam ederken aynı anda yapar. Bu işleme tam GC adı verilir. Bu tür iki koleksiyonerCMS and G1.

Şimdi bu algoritmaları ayrıntılı olarak analiz edelim.

Seri GC

istemci sınıfı makinelerde (tek işlemcili makineler veya 32b JVM, Windows) varsayılan GC'dir. Tipik olarak, GC'ler çok iş parçacıklıdır, ancak seri GC değildir. Yığını işlemek için tek bir iş parçacığı vardır ve küçük bir GC veya büyük bir GC yaptığında uygulama iş parçacıklarını durdurur. JVM'ye bayrağı belirterek bu GC'yi kullanması için komut verebiliriz:-XX:+UseSerialGC. Farklı bir algoritma kullanmasını istiyorsak, algoritma adını belirtin. Eski neslin büyük bir GC sırasında tamamen sıkıştırıldığını unutmayın.

Verimlilik GC

Bu GC, 64b JVM'lerde ve çok CPU'lu makinelerde varsayılandır. Seri GC'den farklı olarak, genç ve eski nesli işlemek için birden çok iş parçacığı kullanır. Bu nedenle, GC aynı zamandaparallel collector. JVM'imize bu toplayıcıyı şu bayrağı kullanarak kullanması için komut verebiliriz:-XX:+UseParallelOldGC veya -XX:+UseParallelGC(JDK 8 sonrası için). Uygulama iş parçacıkları, büyük veya küçük bir çöp toplama işlemi yaparken durdurulur. Seri toplayıcı gibi, büyük bir GC sırasında genç nesli tamamen sıkıştırır.

Aktarım hızı GC, YG ve OG'yi toplar. Eden dolduğunda, toplayıcı canlı nesneleri ondan OG'ye veya hayatta kalan alanlardan birine (aşağıdaki diyagramda SS0 ve SS1) çıkarır. Ölü nesneler, işgal ettikleri alanı boşaltmak için atılır.

YG'nin GC'sinden önce

YG'nin GC'sinden sonra

Tam bir GC sırasında, aktarım hızı toplayıcısı tüm YG, SS0 ve SS1'i boşaltır. Operasyondan sonra OG yalnızca canlı nesneleri içerir. Yukarıdaki toplayıcıların her ikisinin de yığını işlerken uygulama iş parçacıklarını durdurduğuna dikkat etmeliyiz. Bu, büyük bir GC sırasında uzun "dünyayı durdur" duraklamaları anlamına gelir. Sonraki iki algoritma, daha fazla donanım kaynağı pahasına bunları ortadan kaldırmayı hedefliyor -

CMS Toplayıcı

"Eşzamanlı işaret taraması" anlamına gelir. İşlevi, eski nesli periyodik olarak taramak için bazı arka plan konuları kullanması ve ölü nesnelerden kurtulmasıdır. Ancak küçük bir GC sırasında, uygulama iş parçacıkları durdurulur. Ancak, duraklamalar oldukça azdır. Bu, CMS'yi düşük duraklamalı bir toplayıcı yapar.

Bu toplayıcı, uygulama iş parçacıkları çalıştırılırken yığın içinde tarama yapmak için ek CPU zamanına ihtiyaç duyar. Ayrıca, arka plan iş parçacıkları yalnızca yığını toplar ve herhangi bir sıkıştırma gerçekleştirmez. Yığının parçalanmasına neden olabilirler. Bu devam ederken, belirli bir süre sonra, CMS tüm uygulama iş parçacıklarını durduracak ve tek bir iş parçacığı kullanarak yığını sıkıştıracaktır. JVM'ye CMS toplayıcısını kullanmasını söylemek için aşağıdaki JVM bağımsız değişkenlerini kullanın -

“XX:+UseConcMarkSweepGC -XX:+UseParNewGC” JVM argümanları olarak CMS toplayıcısını kullanmasını söyler.

GC'den önce

GC'den sonra

Koleksiyonun eşzamanlı olarak yapıldığını unutmayın.

G1 GC

Bu algoritma, yığını birkaç bölgeye bölerek çalışır. CMS toplayıcı gibi, küçük bir GC yaparken uygulama iş parçacıklarını durdurur ve uygulama iş parçacıklarını devam ettirirken eski nesli işlemek için arka plan iş parçacıklarını kullanır. Eski nesli bölgelere ayırdığı için, nesneleri bir bölgeden diğerine taşırken onları sıkıştırmaya devam ediyor. Bu nedenle parçalanma minimumdur. Bayrağı kullanabilirsiniz:XX:+UseG1GCJVM'nize bu algoritmayı kullanmasını söylemek için. CMS gibi, aynı zamanda öbeği işlemek ve uygulama iş parçacıklarını aynı anda çalıştırmak için daha fazla CPU zamanına ihtiyaç duyar.

Bu algoritma, birkaç farklı bölgeye bölünmüş daha büyük yığınları (> 4G) işlemek için tasarlanmıştır. Bu bölgelerin bir kısmı genç nesli, geri kalanı ise yaşlıları oluşturuyor. YG, geleneksel olarak kullanılarak temizlenir - tüm uygulama iş parçacıkları durdurulur ve eski nesil veya hayatta kalan alan için hala canlı olan tüm nesneler.

Tüm GC algoritmalarının yığını YG ve OG'ye böldüğünü ve YG'yi temizlemek için bir STWP kullandığını unutmayın. Bu süreç genellikle çok hızlıdır.