Yazar | Code Hai
Kaynak | Code Sea (ID: seaofcode)
Sorumlu Editör | Wu Xingling
Java'nın C / C ++ ile karşılaştırıldığında en önemli özelliği, C / C ++ 'nın en zahmetli bellek yönetimi sorununu çözen ve programcıların programa odaklanmasına olanak tanıyan otomatik çöp toplamanın (bundan sonra GC otomatik çöp toplamaya atıfta bulunmak için kullanılacaktır) tanıtılmasıdır. Kendi başına bellek geri dönüşümü konusunda endişelenmenize gerek yok, bu Java'nın bu kadar popüler olmasının önemli nedenlerinden biridir. GC gerçekten programcıların üretkenliğini serbest bırakır, ancak programcıların varlığını algılaması zordur. Yemekten sonra tabakları masanın üzerine koyun ve çıkın, garson bu tabakları sizin için temizleyecektir, garsonun onları ne zaman toplayacağı ve nasıl toplayacağı umurunuzda değil.
Bazı insanlar, GC temizliği otomatik olarak tamamladığından, GC'yi anlamamakta yanlış bir şey olmadığını söylüyor. Çoğu durumda sorun yoktur, ancak bazı performans ayarı, sorun giderme vb. İçeriyorsa, GC'nin derinlemesine anlaşılması hala gereklidir.Meituan, hizmet yanıt süresini TP90 ve TP99'u azaltmak için JVM ile ilgili GC parametrelerini ayarladıktan sonra. 10ms + sonrasında, hizmet kullanılabilirliği büyük ölçüde iyileştirildi! Bu nedenle, derinlemesine bir GC anlayışı, iyi bir Java programcısı olmak için gerekli bir derstir!
Çöp toplama iki bölüme ayrılmıştır, ilk bölüm öncelikle aşağıdakileri içeren çöp toplama teorisinden bahsedecektir:
Sonraki bölüm, esas olarak aşağıdakileri içeren çöp toplama uygulamasına odaklanmaktadır:
Bu makale çöp toplamayı aşağıdaki yönlerden açıklayacaktır:
Pek çok metin var, ancak okuyucuların anlamasını kolaylaştırmak için pek çok GC animasyonu eklendi.İzledikten sonra çok fazla kazanım olacağına inanıyorum.
Çöp toplama mekanizmasını anlamak için önce çöp toplamanın esas olarak hangi verileri topladığını ve verilerin esas olarak hangi alanda olduğunu bilmemiz gerekir, bu nedenle JVM'nin bellek alanına birlikte bakalım
Bu numaraları kaydetmenin ne faydası var? Java sanal makinesinin çoklu okuma işleminin sırayla iş parçacıkları arasında geçiş yaparak ve işlemci zamanı tahsis ederek gerçekleştirildiğini biliyoruz. Herhangi bir zamanda, bir işlemci yalnızca bir iş parçacığı yürütecektir. Bu iş parçacığının ayrılan zaman dilimi yürütüldüğünde (iş parçacığı askıya alındı), işlemci yürütmek için başka bir iş parçacığına geçecektir.Parlak olan iş parçacığının bir sonraki çalıştırılışında (iş parçacığını uyandırmak), en son nerede olduğunu nasıl anlarsınız? Program sayacına kaydedilen satır numarası göstergesinden bilinebilir, bu nedenle program sayacının ana işlevi, iş parçacığının çalışma durumunu kaydetmektir, böylece iş parçacığı uyandırıldığında, en son askıya alındığı durumdan çalışmaya devam edebilir. Program sayacının, Java Sanal Makinesi spesifikasyonunda herhangi bir OOM koşulu belirtmeyen tek alan olduğunu ve bu nedenle bu alanın GC gerektirmediğini unutmayın.
Seslendirme: Bir problem hakkında düşündüğünüzde, yığın dışı bellek GC tarafından kontrol edilmez ve GC aracılığıyla serbest bırakılamaz. O zaman hangi biçimde serbest bırakılmalı? Onu sadece yaratamaz ve bırakamazsınız.Bu durumda, hafıza yakında dolabilir. Ayrıntılı açıklama için lütfen makalenin sonundaki referans makalesine bakın.
Önceki bölümde, JVM'nin bellek alanını ayrıntılı olarak tanımladık.GC'nin esas olarak yığın içinde oluştuğunu bilerek, GC, nesne örneğinin veya yığındaki verilerin çöp olup olmadığını nasıl belirler veya belirli verilerin çöp olup olmadığını belirlemek için hangi yöntemler vardır? .
Düşünmenin en kolay yolu referans sayma yöntemidir.Referans sayma yöntemi olarak adlandırılır. Basitçe ifade etmek gerekirse, nesneye bir kez referans verilir ve referansların sayısı nesne başlığına eklenir. Referans verilmiyorsa (referans sayısı 0'dır), Daha sonra bu nesne geri dönüştürülebilir.
Stringref = newString ("Java");Yukarıdaki ref1 kodu sağda tanımlanan nesneye atıfta bulunur, bu nedenle referans sayısı 1'dir.
Yukarıdaki koddan sonra bir ref = null eklerseniz, nesneye başvurulmadığından, referans sayısı 0 olarak ayarlanır ve herhangi bir değişken tarafından başvurulmadığından bu sefer geri dönüştürülür. Animasyon aşağıdaki gibidir.
Görünüşe göre referans sayma ile ilgili bir sorun yok, ancak büyük bir sorunu çözemez: döngüsel referanslar! Döngüsel referans nedir?
publicclassTestRC {TestRCinstance; publicTestRC (Stringname) {} publicstaticvoidmain (Stringargs) {// İlk adım Aa = newTestRC ("a"); Bb = newTestRC ("b"); // İkinci adım a.instance = b; b .instance = a; // Üçüncü adım a = null; b = null;}}Adım adım bir resim çizin:
Üçüncü adımda, hem a hem de b null olarak ayarlansa da, işaret ettikleri nesneler birbirlerini gösterdikleri için (referans sayısı 1'dir), geri dönüştürülemezler, çünkü tam olarak dairesel referans problemi çözülemez. Bu nedenle, modern sanal makineler, bir nesnenin geri dönüştürülmesi gerekip gerekmediğini belirlemek için referans sayımı kullanmaz.
Modern sanal makineler temelde bir nesnenin canlı olup olmadığını belirlemek için bu algoritmayı kullanır.Erişilebilirlik algoritmasının prensibi, GC Kökü adı verilen bir dizi nesneden başlar, işaret ettikleri bir sonraki düğüme ve ardından başlangıç noktası olarak sonraki düğüme götürür. Bu düğüm tarafından gösterilen sonraki düğüme gidin. . . (Bu şekilde, GC Kökü tarafından dizilen bir satıra referans zinciri denir), tüm düğümler geçilene kadar, ilgili nesneler GC Kökünden başlayan herhangi bir referans zincirinde değilse, bu nesneler "çöp" olarak değerlendirilecektir. ", GC tarafından geri dönüştürülecektir.
Şekilde gösterildiği gibi, erişilebilirlik algoritması yukarıdaki dairesel referans problemini çözmek için kullanılırsa, a ve b'ye GC Kökünden ulaşılamadığından, a ve b geri dönüştürülebilir.
a, b Nesne geri dönüştürülebilir ise, geri kazanılacak mı? Hayır, nesnenin finalize yöntemi nesneye mücadele etme şansı verir. Nesne erişilemez olduğunda (geri dönüştürülebilir), bir GC oluştuğunda, önce nesnenin olup olmadığını belirleyecektir. Finalize yöntemi çalıştırılır.İşlem yapılmazsa, önce finalize yöntemi çalıştırılır.Bu yöntemde mevcut nesneyi GC Roots ile ilişkilendirebiliriz, böylece finalize yöntemini çalıştırdıktan sonra, GC nesnenin tekrar ulaşılabilir olup olmadığına karar verir. Erişilebilir değilse, o zaman Ulaşılabilirse geri dönüştürülecek, geri dönüştürülmeyecek!
Not: Sonlandırma yöntemi yalnızca bir kez yürütülecektir.Nesne, sonlandırma yöntemi ilk çalıştırıldığında erişilebilir hale gelirse, geri dönüştürülmez, ancak nesne yeniden GC ise, sonlandırma yöntemi göz ardı edilir ve nesne geri dönüştürülür! Hatırla bunu!
Peki bu GC Kökleri tam olarak nedir ve hangi nesneler GC Kökleri olarak kullanılabilir? Aşağıdaki kategoriler vardır
Aşağıdaki kodda gösterildiği gibi, a, yığın çerçevesindeki yerel bir değişkendir. A = null olduğunda, a şu anda bir GC Kökü gibi davrandığından, a, new Test () 'in işaret ettiği orijinal örnekten ayrılır, böylece nesne Geri dönüşüm.
publicclassTest {publicstaticvoidmain (Stringargs) {Testa = newTest (); a = null;}} Yöntem alanında sınıf statik özellikleri tarafından başvurulan nesnelerAşağıdaki kodda gösterildiği gibi, yığın çerçevesindeki yerel değişken a = null olduğunda, a ile gösterilen nesnenin GC Kökü (değişken a) ile bağlantısı kesildiği için, a ile gösterilen nesne geri dönüştürülecektir ve s verdiğimiz için Bir değişken referansı atanır, s şu anda sınıfın statik bir özellik referansıdır, bir GC Kökü olarak işlev görür ve işaret ettiği nesne hala canlıdır!
publicclassTest {publicstaticTests; publicstaticvoidmain (Stringargs) {Testa = newTest (); a.s = newTest (); a = null;}} Yöntem alanında sabitler tarafından başvurulan nesnelerAşağıdaki kodda gösterildiği gibi, s sabitiyle gösterilen nesne geri dönüştürülmeyecektir çünkü a ile gösterilen nesne geri dönüştürülmüştür.
publicclassTest {publicstaticfinalTests = newTest (); publicstaticvoidmain (Stringargs) {Testa = newTest (); a = null;}} Yerel yöntem yığınında JNI tarafından başvurulan nesnelerBu, yerel yöntemin ne olduğunu bilmeyen çocuk ayakkabıları için basit bir açıklamadır: Sözde yerel yöntem, Java'da Java olmayan kodu çağırmak için bir arayüzdür. Bu yöntem Java'da uygulanmaz ve C veya Python gibi diğer dillerde de uygulanabilir. Java JNI kullanır. Yerel yöntemi çağırmak için ve yerel yöntem bir kitaplık dosyası biçiminde saklanır (WINDOWS platformunda DLL dosyası, UNIX makinesinde SO dosyası). Yerel kütüphane dosyalarının dahili yöntemlerini çağırarak, JAVA yerel makine ile yakın bağlantıyı gerçekleştirebilir ve sistem düzeyinde arayüz yöntemlerini çağırabilir, yoksa anlamıyor musunuz? Yerel yöntemlerin tanımı ve kullanımına ayrıntılı bir giriş için makalenin sonundaki referansa bakın.
Bir Java yöntemi çağrılırken, sanal makine bir yığın çerçevesi oluşturur ve bunu Java yığınına iter.Yerel bir yöntemi çağırdığında, sanal makine Java yığınını değiştirmeden tutar ve Java yığın çerçevesine yeni bir çerçeve göndermez. Makine, dinamik olarak bağlanır ve belirtilen yerel yöntemi doğrudan çağırır.
JNIEXPORTvoidJNICALLJava_com_pecuyu_jnirefdemo_MainActivity_newStringNative (JNIEnv * env, jobjectinstance, jstringjmsg) {... // cached String classjclassjc = (* env) - > FindClass (env, STRING_PATH);Yukarıdaki kodda gösterildiği gibi, Java yukarıdaki yerel yöntemi çağırdığında, JC yerel yöntem yığını tarafından yığına itilecektir.JC, yerel yöntem yığınında JNI nesne referansı dediğimiz şeydir, bu nedenle yalnızca bu yerel yöntem çalıştırıldıktan sonra gerçekleştirilecektir. yayınlandı.
Önceki bölümde, erişilebilirlik algoritmasının hangi verilerin çöp olduğunu belirlemek için kullanılabileceğini, dolayısıyla bu çöpün nasıl geri dönüştürüleceğini öğrendik. Esas olarak aşağıdaki yollar var
Adımlar basit
Yığını A ve B olmak üzere iki alana bölün. Alan A, nesnelerin tahsis edilmesinden sorumludur ve alan B tahsis edilmemiştir. Kalan nesneleri işaretlemek için yukarıda belirtilen gösterim yöntemini A alanı için kullanın (aşağıdaki şeklin silinmesine gerek yoktur) ve sonra A alanındaki tüm hayatta kalan nesneler B alanına kopyalanır (hayatta kalan nesneler sırayla yan yana düzenlenir) Son olarak, alan A'daki tüm nesneler boş alan açmak için temizlenir ve bu da bellek parçalanması sorununu çözer.
Bununla birlikte, kopyalama algoritmasının eksiklikleri açıktır: Örneğin, yığına 500M bellek tahsis edilirse, yalnızca 250M kullanılabilir ve alan hiçbir neden olmaksızın yarı yarıya azalır! Bu kesinlikle kabul edilemez! Ek olarak, hayatta kalan nesneler her geri dönüştürüldüğünde diğer yarısına taşınmalıdır, bu verimsizdir (dizi öğelerini silmeyi ve ardından silinmemiş öğeleri bir uca kaydırmayı düşünebiliriz, verimlilik açıkça endişe vericidir)
İlk iki adım, işaret kaldırma yöntemiyle aynıdır, fark, işaret kaldırma yöntemine bir sıralama işlemi eklemesidir, yani hayatta kalan tüm nesneler, yan yana düzenlenmiş (şekilde gösterildiği gibi) bir uca taşınır ve ardından diğer uç temizlenir. Bu şekilde bellek parçalanması sorunu çözülür.
Ancak eksiklikler de açıktır: hayatta kalan nesneler, çöp her kaldırıldığında sıklıkla taşınır ve bu çok verimsizdir.
Kuşak toplama algoritması, yukarıdaki algoritmaları entegre eder, bu algoritmaların avantajlarını birleştirir ve eksikliklerinden büyük ölçüde kaçınır.Bu nedenle modern sanal makinelerin kullandığı tercih edilen algoritmadır.O kadar da bir algoritma değildir, bir strateji değildir çünkü Yukarıda bahsedilen algoritmaları entegre eder. Neden nesillere göre toplamanız gerekiyor? Nesnelerin dağılımının hangi kuralları olduğunu görelim.
Şekilde gösterildiği gibi: dikey eksen tahsis edilen baytları temsil eder ve yatay eksen program çalışma süresini temsil eder
Şekilden, nesnelerin çoğunun kısa ömürlü olduğu ve kısa bir süre içinde kurtarıldığı görülebilir (IBM profesyonel araştırması, genel olarak, Minor GC'den sonra nesnelerin% 98'inin öldüğünü göstermektedir. Geri dönüştürülecek), bu nedenle kuşak toplama algoritması, yığını nesnenin yaşam döngüsüne göre genç nesil ve eski nesil olarak ayırır (Java 8'den önce kalıcı bir nesil vardır), varsayılan oran 1: 2'dir, yeni nesil, Eden alanına bölünür. Survivor alanı (S0 olarak kısaltılır), Survivor alanına (S1 olarak kısaltılır), üçünün oranı 8: 1: 1'dir, böylece yeni ve eski nesillerin özelliklerine göre en uygun çöp toplama algoritmasını seçebiliriz. GC, Young GC (Minor GC olarak da adlandırılır) ve yaşlılıkta oluşan GC, Old GC (Full GC olarak da adlandırılır) olarak adlandırılır.
Seslendirme: Bir düşünün, yeni nesil neden bu kadar çok bölgeye sahip?
Peki, nesilsel çöp toplama nasıl çalışıyor?
Nesil toplama nasıl çalışır?1. Yeni nesil nesnelerin tahsisi ve kurtarılması
Yukarıdaki analizden, çoğu nesnenin kısa bir süre içinde geri dönüştürüleceği ve nesnelerin genellikle Eden alanında tahsis edildiği görülebilir.
Eden alanı neredeyse dolduğunda, Minor GC'yi tetikleyin
Daha önce söylediğimiz gibi, çoğu nesne kısa sürede geri dönüştürülecek, bu nedenle Minor GC'den sonra sadece birkaç nesne hayatta kalacak ve S0 alanına taşınacaklar (bu nedenle Eden uzayının boyutu: S0: S1 = 8: 1: 1, Eden alanının S0, S1'den çok daha büyük olmasının nedeni, Eden alanında tetiklenen Küçük GC'nin nesnelerin çoğunu (% 98'e yakın) geri kazanması ve yalnızca az sayıda hayatta kalan nesne bırakmasıdır, bu yüzden onları taşıyın S0 veya S1 fazlasıyla yeterli) Aynı zamanda nesnenin yaşı bir artar (nesnenin yaşı, Küçük GC'nin oluşma sayısıdır) ve son olarak Eden alanındaki tüm nesneler, yer açmak için temizlenir. Animasyon aşağıdaki gibidir.
Bir sonraki Küçük GC tetiklendiğinde, Eden alanında hayatta kalan nesneler ve S0 (veya S1) 'de hayatta kalan nesneler (S0 veya S1'deki hayatta kalan nesneler, her Küçük GC'den sonra geri alınabilir) S1'e (Eden ve S0'ın hayatta kalan nesne yaşı +1'dir) ve Eden ve S0'ın alanı aynı anda temizlenir.
Bir sonraki Küçük GC tekrar tetiklenirse, önceki adım tekrarlanacaktır, ancak şimdi Eden'den gelir.S1 alanı hayatta kalan nesneleri S0 alanına kopyalayacaktır. Çöp toplama her seferinde, S0 ve S1 rolleri Eden'den değiştirilir. S0 (veya S1) hayatta kalan nesneyi S1'e (veya S0) taşır. Yani Eden bölgesinin çöp toplamasında çoğaltma algoritmasını kullanıyoruz, çünkü Eden alanında tahsis edilen nesnelerin çoğu Küçük GC'den sonra yok oluyor ve hayatta kalan nesnelerin sadece küçük bir kısmı kalıyor (bu yüzden Eden: S0: S1 varsayılan olarak 8: 1: 1'dir) S0 ve S1 alanları da nispeten küçüktür, bu nedenle çoğaltma algoritmasının neden olduğu sık nesne kopyalamanın neden olduğu ek yük en aza indirilir.
2. Denek ne zaman yaşlılığa yükseltilecek?
3. Alan tahsisi garantisi
MinorGC'nin ortaya çıkmasından önce, sanal makine ilk olarak eski nesildeki mevcut en büyük sürekli alanın yeni nesildeki tüm nesnelerin toplam alanından daha büyük olup olmadığını kontrol eder. Daha büyükse, Minor GC güvenli olduğundan emin olabilir. Şundan büyük değilse sanal makine HandlePromotionFailure ayar değerinin olup olmadığını kontrol eder. Garantinin başarısız olmasına izin verin. İzin verilirse, eski nesildeki maksimum kullanılabilir sürekli alanın eski nesle yükseltilen nesnelerin ortalama boyutundan daha büyük olup olmadığını kontrol etmeye devam edecektir, eğer bundan daha büyükse, bir Minor GC gerçekleştirilecektir, aksi takdirde bir Full GC gerçekleştirilebilir.
4. Dünyayı Durdurun
Eski nesil doluysa, Tam GC tetiklenecektir Tam GC, hem genç nesli hem de eski nesli aynı anda geri kazanacaktır (yani, GC tüm yığın), bu da Dünyayı Durdur'a (STW olarak kısaltılmıştır) ve çok fazla performans yüküne neden olacaktır.
STW nedir? Sözde STW, yani GC sırasında (küçük GC veya Tam GC), yalnızca çöp toplayıcı iş parçacığı çalışıyor ve diğer çalışan iş parçacıkları askıya alındı.
Seslendirme: Çöp toplama sırasında diğer çalışan iş parçacıkları neden askıya alınır? Başka bir grup insan çöpü atarken çöp topladığınızı hayal edin Çöpler temizlenebilir mi?
Genel olarak, Tam GC, çalışan iş parçacığının çok uzun süre duraklamasına neden olur (çünkü Tam GC, tüm yığındaki kullanılamayan nesneleri temizler, bu genellikle uzun sürer), sunucu çok fazla istek alırsa, hizmet reddedilir! Bu nedenle, Tam GC'yi en aza indirmeliyiz (Küçük GC de STW'ye neden olur, ancak sadece hafif bir STW tetiklenecektir, çünkü Eden alanındaki nesnelerin çoğu geri dönüştürülmüştür ve yalnızca birkaç hayatta kalan nesne çoğaltma algoritması aracılığıyla S0 veya S1 alanına aktarılacaktır. , Yani nispeten iyi).
Şimdi anlamalıyız ki, genç nesli Eden, S0, S1 alanına ayarlamanın veya nesne için yaş eşiğini belirlemenin veya genç neslin ve eski neslin alan boyutunu varsayılan olarak 1: 2'ye ayarlamanın, nesnenin eskiye erken girmesini önlemek olduğunu anlamalıyız. Tam GC, olabildiğince geç tetiklenir. Sadece yeni nesilde Eden'i ayarlarsanız ne olacağını düşünün.Sonuç, her Minor GC'den sonra, hayatta kalan nesnelerin eski nesle erken girmesi, daha sonra eski nesil hızla dolması ve Full GC'nin yakında tetiklenmesidir, ancak nesne aslında İki veya üç Küçük GC'den sonra çoğu ölecek, bu nedenle S0 ve S1 tamponlarında sadece birkaç nesne yaşlılığa girecek ve yaşlılığın boyutu o kadar hızlı büyümeyecek, bu da erken doğmayı engelliyor Tam GC'yi tetikleyin.
Tam GC (veya Minor GC) performansı etkileyeceğinden, GC'yi uygun bir zamanda başlatmalıyız. Bu zamandaki bu noktaya Güvenli Nokta denir. Zaman içindeki bu noktanın seçimi, GC süresini çok uzun yapmak için çok küçük olmamalıdır. Program uzun süre takılı kalırsa, çalışma sırasında yükü çok fazla artırmak için çok sık olmamalıdır. Genel olarak, GC Kök bilgisinin belirlenmesi vb. Gibi zamandaki bu noktada iş parçacığının durumu, JVM'nin GC'yi güvenli bir şekilde başlatabilmesi için belirlenebilir. Güvenli Nokta, esas olarak aşağıdaki belirli konumları ifade eder:
Toplama algoritması bellek kurtarma metodolojisiyse, çöp toplayıcı, bellek kurtarmanın spesifik uygulamasıdır. Java sanal makine spesifikasyonu, çöp toplayıcının nasıl uygulanması gerektiğini belirtmez, bu nedenle genel olarak, farklı satıcılar tarafından sağlanan çöp toplayıcının uygulanması ve sanal makinenin farklı versiyonları farklı olabilir.Genel olarak, kullanıcıların uygulamanın özelliklerine göre ayarlamalarına izin verecek parametreler verilir. Çeşitli nesillerde kullanılan toplayıcıları birleştiren başlıca şu çöp toplayıcıları vardır.
Resimdeki çöp toplayıcının bir bağlantısı varsa, birlikte kullanılabilecekleri anlamına gelir.Şimdi, her bir çöp toplayıcının belirli işlevlerine bir göz atalım.
Seri toplayıcı yeni nesilde çalışır.Tek iş parçacıklı bir çöp toplayıcıdır.Tek iş parçacıklı, çöp toplamayı tamamlamak için yalnızca bir CPU veya bir toplama iş parçacığı kullanacağı anlamına gelir.Sadece bu değil, yukarıda bahsedilen STW'yi hatırlıyor musunuz? , Çöp toplama işlemi gerçekleştirirken, diğer kullanıcı iş parçacıkları, çöp toplama bitene kadar askıya alınacaktır, yani, GC sırasında, uygulama şu anda kullanılamaz.
Görünüşe göre tek iş parçacıklı çöp toplayıcı çok pratik değil, ancak bilmemiz gereken herhangi bir teknolojinin kullanımı sahneden ayrılamaz. İstemci modunda, basit ve etkilidir (diğer toplayıcıların tek iş parçacıklı toplayıcıları ile karşılaştırıldığında) ve tek bir CPU'yu sınırlayan ortama uygundur. Diğer bir deyişle, Seri tek iş parçacıklı modun diğer iş parçacıklarıyla etkileşime girmesine gerek yoktur, bu da ek yükü azaltır.GC üzerinde yoğunlaşma, tek iş parçacıklı avantajlarını en üst düzeye çıkarabilir.Ayrıca, kullanıcı masaüstü uygulama senaryolarında, sanal makinelere ayrılan bellek genellikle çok büyük değildir. , Onlarca veya hatta bir veya iki yüz megabayt toplayın (yalnızca yeni nesil bellek, masaüstü uygulamaları temelde daha büyük olmayacaktır), STW süresi 100 milisaniyeden fazla bir süre içinde kontrol edilebilir, sık sık gerçekleşmediği sürece, bu duraklama kabul edilebilir Dolayısıyla, İstemci modunda çalışan sanal makineler için, Seri toplayıcı yeni nesil için varsayılan toplayıcıdır.
ParNew toplayıcıParNew toplayıcı, Seri toplayıcının çok iş parçacıklı bir sürümüdür.Çoklu iş parçacığı kullanmaya ek olarak, diğer toplama algoritmaları, STW, nesne tahsis kuralları ve geri dönüşüm stratejileri, Seri toplayıcınınkilerle aynıdır. Alt seviyede, bu iki toplayıcı da aynı şeyi paylaşır Daha fazla kod, çöp toplama süreci aşağıdaki gibidir
ParNew esas olarak Sunucu modunda çalışır.Sunucu daha fazla istek alırsa yanıt süresinin çok önemli olduğunu biliyoruz.Multithreading, çöp toplamayı daha hızlı hale getirebilir, bu da STW süresini azalttığı ve yanıt süresini iyileştirdiği anlamına gelir. Yeni nesil toplayıcı, Sunucu modunda çalışan sanal makineler için ilk tercihtir.Performansla ilgisi olmayan bir başka neden de Seri toplayıcı dışında yalnızca CMS toplayıcıyla çalışabilmesidir.CMS, çığır açan bir çöp toplayıcıdır. Eşzamanlı toplayıcı anlamında, çöp toplama iş parçacığının ve kullanıcı iş parçacığının (temelde) aynı anda çalıştığını fark eder, geleneksel GC toplayıcı kod çerçevesini kullanır ve Serial, ParNew bir kod çerçevesini paylaşır, böylece Bu ikisiyle birlikte çalışın ve daha sonra bahsedilen Parallel Scavenge ve G1 toplayıcıları geleneksel GC toplayıcı kodu çerçevesini kullanmaz, ancak bağımsız olarak uygulanır. Diğer toplayıcılar çerçeve kodunun yalnızca bir bölümünü paylaşır, bu nedenle CMS toplayıcı ile çalışamaz.
Birden fazla CPU olması durumunda, ParNew'in çok iş parçacıklı geri dönüşüm özelliği nedeniyle, çöp toplamanın daha hızlı olacağına ve ayrıca STW süresini etkili bir şekilde azaltacağına ve uygulama yanıt hızını artırabileceğine şüphe yoktur.
Paralel Temizleme toplayıcıParallel Scavenge toplayıcı aynı zamanda bir çoğaltma algoritması kullanan, çok iş parçacıklı ve yeni nesilde çalışan bir çöp toplayıcıdır.ParNew toplayıcı ile aynı işleve sahip gibi görünüyor.Bununla ilgili özel bir şey var mı?
Odak farklıdır. CMS gibi çöp toplayıcılar, çöp toplama sırasında kullanıcı iş parçacıklarının duraklatma süresini olabildiğince kısaltmaya odaklanırken, Parallel Scavenge'ın amacı kontrol edilebilir bir verim elde etmektir (verim = çalıştırma kullanıcı kodu süresi / (kullanıcı kodu süresini çalıştırma) + Çöp toplama süresi)), yani CMS gibi çöp toplayıcıların kullanıcılarla etkileşime giren programlar için daha uygun olduğu anlamına gelir, çünkü duraklama süresi ne kadar kısaysa kullanıcı deneyimi o kadar iyi olurken, Parallel Scavenge toplayıcı verime odaklanır, bu yüzden daha uygundur Çok fazla kullanıcı etkileşimi gerektirmeyen arka plan hesaplamaları ve diğer görevleri yapın.
Parallel Scavenge toplayıcı, verimi doğru bir şekilde kontrol etmek için iki parametre sağlar. Bunlar, maksimum çöp toplama süresini kontrol eden -XX: MaxGCPauseMillis parametresi ve doğrudan işleme boyutunu ayarlayan -XX: GCTimeRatio'dur (varsayılan% 99)
Yukarıdaki iki parametreye ek olarak, Parallel Scavenge toplayıcı tarafından sağlanan üçüncü parametre -XX: UseAdaptiveSizePolicy'yi de kullanabilirsiniz.Bu parametreyi açtıktan sonra, genç neslin boyutunu, Eden'in Survivor oranını (SurvivorRatio) ve diğer ayrıntıları manuel olarak belirtmenize gerek yoktur. Temel yığın boyutunu (maksimum yığını ayarlamak için -Xmx) ve maksimum çöp toplama süresini ve verimini ayarlayın, sanal makine mevcut sistem işlemine göre izleme bilgilerini toplayacak ve kümemize mümkün olduğunca ulaşmak için bu parametreleri dinamik olarak ayarlayacaktır. Maksimum çöp toplama süresi veya işlem hacmi iki göstergedir. Uyarlanabilir strateji, Parallel Scavenge ve ParNew! Arasında önemli bir farktır.
Yukarıda bildiğimiz gibi, Seri toplayıcı, yeni nesilde çalışan tek iş parçacıklı bir toplayıcıdır.Ancak Serial Old, eski nesilde çalışan tek iş parçacıklı bir toplayıcıdır.Bu koleksiyonerin temel önemi sanal Sunucu modunda kullanılıyorsa, iki ana kullanımı vardır: biri, JDK 1.5 ve önceki sürümlerde Parallel Scavenge ile birlikte kullanılacak, diğeri ise CMS toplayıcı için eşzamanlı toplama sırasında oluşan bir yedekleme planı olarak kullanılacak. Eşzamanlı Mod Arızası olduğunda kullanılır (daha sonra açıklanacaktır), aşağıdaki gibi Seri toplayıcı ile birlikte kullanılır
Paralel Eski toplayıcıParallel Old, Parallel Scavenge toplayıcısının eski sürümüne göredir. Çoklu okuma ve etiket sıralaması kullanır. İkisinin kombinasyonunun şematik diyagramı aşağıdaki gibidir. İkisinin kombinasyonu, gerçekten "önce iş hacmine" ulaşan çok iş parçacıklı bir toplayıcıdır Amaçları
CMS toplayıcıCMS toplayıcı, en kısa STW süresine ulaşmayı hedefleyen bir toplayıcıdır.Uygulama, hizmetin yanıt hızına büyük önem veriyorsa ve kullanıcılara en iyi deneyimi yaşatmak istiyorsa, CMS toplayıcı çok iyi bir seçimdir!
Daha önce yaşlılığın esas olarak işaretleme yöntemini kullandığını ve CMS'nin yaşlılıkta çalışmasına rağmen, esas olarak aşağıdaki dört adımı olan işaret kaldırma yöntemini kullandığını söylemiştik.
STW'nin ilk işaretleme ve yeniden işaretleme aşamalarında meydana geleceği ve kullanıcı iş parçacığının askıda kalmasına neden olacağı şekilden görülebilir, ancak ilk işaretleme yalnızca GC Kökleri ile ilişkilendirilebilen nesneleri işaretler ki bu çok hızlıdır Eşzamanlı işaretleme, GC Kök İzleme sürecidir. Yeniden işaretleme, eşzamanlı işaretleme sırasında kullanıcı ipliğinin devam eden işlemine bağlı olarak işaretlemesi değiştirilen nesnenin parçasının işaretleme kaydını düzeltmektir Bu aşamadaki duraklama süresi genellikle başlangıç işaretleme aşamasından biraz daha uzun, ancak eşzamanlı işaretleme süresinden çok daha kısadır.
Tüm süreçte en uzun zaman alan süreç eş zamanlı işaretleme ve işaretleme temizliğidir.Ancak, kullanıcı iş parçacıkları bu iki aşamada çalışabilir, bu nedenle uygulamanın normal kullanımını etkilemez. Bu nedenle, genel olarak CMS toplayıcısının bellek kurtarma işlemi şu şekilde değerlendirilebilir: Kullanıcı konuları eşzamanlı olarak yürütülür.
Bununla birlikte, CMS toplayıcı mükemmel olmaktan uzaktır ve aşağıdaki üç dezavantaja sahiptir.
G1 toplayıcı, sunucu odaklı bir çöp toplayıcıdır.Her şeyi kontrol eden çöp toplayıcı olarak adlandırılır.Aşağıdaki özelliklere sahiptir.
CMS ile karşılaştırıldığında, aşağıdaki iki açıdan daha iyi performans gösterir
G1 neden öngörülebilir bir duraklama modeli oluşturabilir? Bunun ana nedeni, G1'in yığın alanı tahsisinin geleneksel çöp toplayıcıdan farklı olmasıdır.Geleneksel bellek tahsisi süreklidir, yeni nesillere ve eski nesillere bölünmüştür. Çağda, yeni nesil aşağıdaki gibi Eden, S0, S1'e ayrılmıştır.
Her bir G1 neslinin depolama adresleri sürekli değildir. Her nesil, aynı boyutta n ayrı bölge kullanır ve her bölge, şekilde gösterildiği gibi sürekli bir sanal bellek adresini işgal eder
Geleneksel yeni ve eski nesiller ile hayatta kalma alanı arasındaki mekansal farka ek olarak, Bölgede Humongous anlamına gelen ek bir H vardır, bu da bu Bölgelerin büyük nesneler (H-obj) depoladığı anlamına gelir, yani boyut bölgenin yarısından büyük veya yarısına eşittir. G1
Full GC Region G1 Region Region, STW Region, STW
G1
CMS Region GC
Client Serial + Serial Old ParNew + CMS G1 JVM
demoOOM
referans:
https://www.jianshu.com/p/35cf0f348275
Java--jni https://blog.csdn.net/w1992wishes/article/details/80283403
Java https://mp.weixin.qq.com/s/pR7U1OTwsNSg5fRyWafucA
Java
Java Hotspot G1 GC https://tech.meituan.com/2016/09/23/g1.html