Arasındaki fark nedir java.lang.ref.WeakReference
ve java.lang.ref.SoftReference
?
Arasındaki fark nedir java.lang.ref.WeakReference
ve java.lang.ref.SoftReference
?
Yanıtlar:
Gönderen anlama Zayıf Referanslar Ethan Nicholas tarafından,:
Zayıf referanslar
Bir zayıf bir referans , basitçe hafızada kalma bir nesne zorlamak için yeterince güçlü olmayan bir başvurudur. Zayıf referanslar, çöp toplayıcının sizin için erişilebilirliği belirleme yeteneğinden yararlanmanıza izin verir, böylece bunu kendiniz yapmanız gerekmez. Bunun gibi zayıf bir referans oluşturursunuz:
WeakReference weakWidget = new WeakReference(widget);
ve sonra
weakWidget.get()
asılWidget
nesneyi almak için kodun başka bir yerinde kullanabilirsiniz . Tabii ki zayıf referans çöp toplamayı önleyecek kadar güçlü değil, bu yüzdenweakWidget.get()
aniden geri dönmeye başlayan ( widget'a güçlü referanslar yoksa) bulabilirsiniz.null
....
Yumuşak referanslar
Bir yumuşak bir referans o gelir nesneyi atmak için daha istekli olduğunu hariç tam olarak zayıf bir referans gibidir. Sadece zayıf ulaşılabilir bir nesne (en güçlü referanslar
WeakReferences
) bir sonraki çöp toplama döngüsünde atılacaktır, ancak yumuşak bir şekilde erişilebilen bir nesne genellikle bir süre yapışacaktır.
SoftReferences
değildir gerekli farklı bir şekilde herhangi bir davranmayaWeakReferences
fakat uygulamada yumuşak ulaşılabilir objeler genelde uzun hafıza bol kaynağı olarak muhafaza edilir. Bu, onları yukarıda açıklanan görüntü önbelleği gibi bir önbellek için mükemmel bir temel yapar, çünkü çöp toplayıcının hem nesnelerin ne kadar ulaşılabilir olduğu konusunda endişelenmesine izin verebilirsiniz (güçlü bir şekilde ulaşılabilir bir nesne önbellekten asla kaldırılmaz) ve ne kadar kötü olursa olsun tükettikleri hafızaya ihtiyaç duyarlar.
Ve Peter Kessler bir yorum ekledi:
Sun JRE, SoftReferences'ı WeakReferences'dan farklı olarak ele alır. Kullanılabilir bellek üzerinde baskı yoksa, SoftReference tarafından başvurulan nesneyi tutmaya çalışırız. Bir ayrıntı: "-client" ve "-server" JRE'leri için politika farklıdır: -client JRE, yığını genişletmek yerine SoftReferences'ı temizlemeyi tercih ederek ayak izinizi küçük tutmaya çalışırken -server JRE ise net SoftReferences yerine yığın (mümkünse) genişletmeyi tercih ederek yüksek performans. Tek beden herkese olmaz.
Zayıf referanslar hevesle toplanmaktadır. GC bir nesneye zayıf erişilebildiğini (yalnızca zayıf referanslarla ulaşılabilir) bulursa, o nesneye zayıf referansları derhal temizler. Bu nedenle, programınızın aynı zamanda bir sınıfla ilgili önbelleğe alınmış yansıma bilgileri veya bir nesne için bir sarıcı vb. ilişkili olduğu nesneden sonra tutulması mantıklı değil GC-ed. Zayıf başvuru temizlendiğinde, kodunuzun bir yerde yokladığı bir başvuru kuyruğunda sıralanır ve ilişkili nesneleri de atar. Yani, bir nesne hakkında fazladan bilgi tutarsınız, ancak söz konusu nesne ortadan kalktığında bu bilgilere gerek yoktur. Aslında, belirli durumlarda WeakReference alt sınıfını yapabilir ve nesne hakkında ilişkili ek bilgileri WeakReference alt sınıfının alanlarında saklayabilirsiniz. WeakReference'ın bir diğer tipik kullanımı, kanonik örnekleri korumak için Haritalar ile bağlantılıdır.
Öte yandan SoftReferences, harici, yeniden oluşturulabilir kaynakların önbelleğe alınması için iyidir, çünkü GC genellikle bunları temizlemeyi geciktirir. OutOfMemoryError atılmadan önce tüm SoftReferences'ın temizleneceği garanti edilir, bu nedenle teorik olarak OOME'ye neden olamazlar [*].
Tipik kullanım örneği, dosyadaki içeriklerin ayrıştırılmış bir formunu tutmaktır. Bir dosyayı yüklediğiniz, ayrıştırdığınız ve ayrıştırılmış gösterimin kök nesnesine SoftReference uygulayacağınız bir sistem uygularsınız. Bir dahaki sefere dosyaya ihtiyacınız olduğunda, SoftReference üzerinden almaya çalışacaksınız. Eğer geri getirebilirseniz, kendinize başka bir yük / ayrıştırma bağışladınız ve GC bu arada temizlediyse, yeniden yüklersiniz. Bu şekilde, performans optimizasyonu için boş bellek kullanırsınız, ancak OOME riskini almazsınız.
Şimdi [*] için. SoftReference tutmak kendi içinde bir OOME'ye neden olamaz. Öte yandan, bir görev için yanlışlıkla SoftReference kullanıyorsanız, bir WeakReference'ın kullanılması gerekiyorsa (yani, bir Nesne ile ilişkili bilgileri bir şekilde güçlü bir şekilde referans alırsınız ve Referans nesnesi temizlendiğinde atarsınız), OOME ReferenceQueue'yu yoklayan ve ilişkili nesneleri atayan kodunuz zamanında çalışmayabilir.
Bu nedenle, karar kullanıma bağlıdır - yapılandırılması pahalı olan, ancak yine de diğer verilerden yeniden oluşturulabilen bilgileri önbelleğe alıyorsanız, yumuşak referanslar kullanın - bazı verilerin kanonik örneğine referansta bulunuyorsanız veya bir nesneye "sahip olmadan" referans vermesi (böylece GC'nin olmasını engellemesi) zayıf bir referans kullanın.
WeakReference
, kişinin onu kullanması gereken yerlerde, referansın kapsam dışına çıktıktan sonra bir süre geçerli kalması tolere edilebilir, ancak istenmez.
WeakReference
vardır. Ayrıntılara bakın: stackoverflow.com/a/46291143/632951
Java dilinde ; güçlü, Yumuşak, Zayıf ve Hayalet
Bir güçlü bir referans GC ile koleksiyonundan ifade nesne koruyan normal referanstır. Yani asla çöp toplamaz.
Bir Yumuşak referans çöp toplayıcı tarafından toplama işlemi için uygundur, ama muhtemelen onun bellek gereklidir kadar tahsil edilmeyecektir. yani çöp daha önce toplar OutOfMemoryError
.
Bir Zayıf referans GC ile koleksiyonundan bir başvurulan nesneyi korumaz bir referanstır. Çöp, Güçlü veya Yumuşak referans olmadığında toplanır.
Bir Phantom referansı , sonlandırıldıktan sonra, ancak ayrılan belleği geri kazanılmadan önce, bir nesneye hayali olarak atıfta bulunulan bir referanstır.
Analoji: Bir JVM'nin bir krallık olduğunu, Object'in krallığın bir kralı olduğunu ve GC krallığın (nesne) öldürmeye çalışan bir krallığın saldırganı olduğunu varsayalım.
until memory is available
mantıklı değil. Bunu mu demek istediniz is eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use
?
Zayıf Referans http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html
İlke: weak reference
çöp toplama ile ilgilidir. Normalde, bir veya daha fazlasına sahip nesne reference
çöp toplama için uygun olmaz.
Yukarıdaki ilke, geçerli olduğunda geçerli değildir.weak reference
. Bir nesnenin diğer nesnelerle yalnızca zayıf bir referansı varsa, o zaman çöp toplama için hazırdır.
Aşağıdaki örneğe bakalım: Map
Anahtarın bir nesneye başvurduğu Nesneleri olan bir.
import java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> aMap = new
HashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("Programmer");
aMap.put(emp, val);
emp = null;
System.gc();
System.out.println("Size of Map" + aMap.size());
}
}
Şimdi programın yürütülmesi sırasında yaptık emp = null
. Map
Olduğu gibi tutma anahtarı burada hiçbir mantıklı null
. Yukarıdaki durumda, nesne çöp toplanmaz.
WeakHashMap
WeakHashMap
, girişlerin ( key-to-value mappings
) artık girişlerden alınamadığında kaldırılacağı yerdir .Map
.
Yukarıdaki örneği WeakHashMap ile aynı şekilde göstereyim
import java.util.WeakHashMap;
public class Test {
public static void main(String args[]) {
WeakHashMap<Employee, EmployeeVal> aMap =
new WeakHashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("Programmer");
aMap.put(emp, val);
emp = null;
System.gc();
int count = 0;
while (0 != aMap.size()) {
++count;
System.gc();
}
System.out.println("Took " + count
+ " calls to System.gc() to result in weakHashMap size of : "
+ aMap.size());
}
}
Çıktı: Şununla 20 calls to System.gc()
sonuçlandı aMap size
: 0.
WeakHashMap
diğer Map
sınıflar gibi güçlü referanslar değil, anahtarlar için sadece zayıf referanslar vardır . Kullanmış olsanız da, değere veya anahtara güçlü bir şekilde başvurulduğunda dikkat etmeniz gereken durumlar vardır WeakHashMap
. Bu, nesneyi bir WeakReference öğesine sararak önlenebilir .
import java.lang.ref.WeakReference;
import java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> map =
new HashMap<Employee, EmployeeVal>();
WeakReference<HashMap<Employee, EmployeeVal>> aMap =
new WeakReference<HashMap<Employee, EmployeeVal>>(
map);
map = null;
while (null != aMap.get()) {
aMap.get().put(new Employee("Vinoth"),
new EmployeeVal("Programmer"));
System.out.println("Size of aMap " + aMap.get().size());
System.gc();
}
System.out.println("Its garbage collected");
}
}
Yazılım Referansları.
Soft Reference
zayıf referanstan biraz daha güçlüdür. Yumuşak referans çöp toplanmasına izin verir, ancak çöp toplayıcıya yalnızca başka bir seçenek yoksa temizlemesini ister.
Çöp toplayıcı, yumuşak erişilebilen nesneleri zayıf erişilebilen nesnelerle olduğu gibi agresif bir şekilde toplamaz - bunun yerine yalnızca belleğe gerçekten ihtiyaç duyması durumunda yumuşak erişilebilen nesneleri toplar. Yumuşak referanslar çöp toplayıcısına, "Bellek çok sıkı olmadığı sürece, bu nesneyi saklamak istiyorum. Ama eğer bellek gerçekten sıkılaşırsa, devam edin ve toplayın ve ilgileneceğim Bununla." Çöp toplayıcının atmadan önce tüm yumuşak referansları temizlemesi gerekir OutOfMemoryError
.
NullPointerException
in aMap.get().put(...)
.
WeakHashMap
(çünkü Zayıf davranışı gösteren ilk örnek budur). "WeakHashMap" için doc bak: "An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. "
WeakHashMap kullanarak tüm noktasının olmasıdır sen pass-bir WeakReference / beyan etmek gerekmez; WeakHashMap bunu sizin için dahili olarak yapar. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html
WeakHashMap
girişleri sadece kaldırılır nasıl örnek uygulama gösterimiyle eylem, sonra çöp toplama çalıştırır, bkz benim cevap Soru, Is WeakHashMap büyüyen ya da çöp anahtarlarını temizleyin geliyor? .
Yumuşak referans ile zayıf referans arasındaki tek gerçek fark,
çöp toplayıcı, yumuşak bir şekilde erişilebilen bir nesneyi geri alıp almayacağınıza karar vermek için algoritmalar kullanır, ancak her zaman zayıf bir şekilde erişilebilir bir nesneyi geri alır.
SoftReference
önbellekler için tasarlanmıştır. WeakReference
Aksi takdirde ulaşılamayan bir nesneye başvurduğu tespit edildiğinde , derhal temizlenecektir. SoftReference
olduğu gibi bırakılabilir. Genellikle boş bellek miktarı ve silinmesi gerekip gerekmediğini belirlemek için en son kullanılan zamanla ilgili bazı algoritmalar vardır. Geçerli Sun algoritması, Java yığınında megabayt bellek kadar boşta kaldığı sürece referansı temizlemektir (yapılandırılabilir, sunucu HotSpot, ayarlandığı gibi mümkün olan en fazla yığını denetler -Xmx
). Aksi takdirde erişilemezse, atılmadan SoftReference
önce silinecektir OutOfMemoryError
.
java.lang
. Eşanlamlıların bu şekilde kötüye kullanılması hiç kimseye iyi bir şey yapmaz.
Bu makale güçlü, yumuşak, zayıf ve hayali referansları anlamak için çok yardımcı olabilir.
Size bir özet vermek için,
Yalnızca zayıf referanslarınız varsa nesneye (güçlü referanslar olmadan) varsa, nesne bir sonraki GC döngüsünde GC tarafından geri kazanılır.
Bir nesneye yalnızca yumuşak referanslarınız varsa (güçlü referanslar olmadan), nesne yalnızca JVM belleği dolduğunda GC tarafından geri kazanılır.
Yani güçlü referansların nihai güce sahip olduğunu söyleyebilirsiniz. (GC tarafından asla toplanamaz)
Yumuşak referanslar güçlüdür zayıf referanslardan daha (JVM hafızası bitene kadar GC döngüsünden çıkabilirler)
Zayıf referanslar, yumuşak referanslardan bile daha az güçlüdür (çünkü herhangi bir GC döngüsünü çıkaramazlar ve nesnenin başka güçlü referansı yoksa geri kazanılırlar).
Restoran Analojisi
Şimdi güçlü bir müşteri iseniz (güçlü referansa benzer), o zaman yeni bir müşteri restorana gelse veya ne olursa olsun, masanızı asla bırakmayacaksınız (yığıntaki bellek alanı). Garson, restorandan ayrılmak için size söyleme hakkına (hatta sizden talepte bulunmaya) hakkı yoktur.
Eğer bir ise yumuşak müşteri (yumuşak referans benzer) Yeni bir müşteri restoranda gelirse yeni müşteri karşılamak için sol başka hiçbir boş masa olmadığı sürece, o zaman, garson masayı terk etmek istemez. (Diğer bir deyişle, garson sadece yeni bir müşteri devreye girerse ve bu yeni müşteri için başka bir masa kalmamışsa masadan çıkmanızı isteyecektir)
Eğer bir ise zayıf müşteri (zayıf referans benzer), sonra garson, onun iradesiyle, (zamanın herhangi bir noktasında) restoran terk etmenizi isteyebilir: P
Başına doc , gevşek WeakReferences gerekir çalışan bir GC ile temizlenir.
Başına doc , gevşek SoftReferences gerekir OOM önce temizlenecek atılır.
Tek gerçek fark bu. Diğer her şey sözleşmenin bir parçası değildir. (En son dokümanların sözleşmeye bağlı olduğunu varsayacağım.)
SoftReferences yararlıdır. Belleğe duyarlı önbellekler WeakReferences değil SoftReferences kullanır.
weak_ref.get()
. Olduğu zamannull
, bu süre arasında GC'nin koştuğunu öğrenirsiniz.
WeakReference yanlış kullanımına gelince , liste sonsuzdur:
öncelik-2 yazılımını uygulamak için berbat bir saldırı, böylece bir tane yazmak zorunda kalmazsınız, ancak yedek bellek olsa bile önbellek her GC çalışmasında temizleneceği için beklendiği gibi çalışmaz . Filler için https://stackoverflow.com/a/3243242/632951 adresine bakın . (Ayrıca, 2'den fazla önbellek önceliğine ihtiyacınız varsa? Hala bunun için gerçek bir kütüphaneye ihtiyacınız olacak.)
Berbat bir hack varolan sınıfının bir nesne ile ilişkilendirmek verilere, henüz senin GC sizin weakreferences oluşturulduktan sonra bir mola karar verdiğinde bir bellek sızıntısı (OutOfMemoryError) oluşturur. Ayrıca, çirkin ötesinde: Daha iyi bir yaklaşım tuples kullanmaktır.
sınıfın kendisini alt sınıflandırılamayan bir sinire sahip olduğu ve çağırmanız gereken mevcut bir işlev kodunda kullanıldığı, mevcut bir sınıfın nesnesiyle verileri ilişkilendirmek için berbat bir saldırı . Böyle bir durumda, uygun çözüm ya sınıfı düzenlemek ve alt sınıflanabilir yapmak ya da işlevi düzenlemek ve sınıf yerine arabirim almasını sağlamak ya da alternatif bir işlev kullanmaktır.
equals()
sadece nesne kimliği olduğu bir önbellek ne olacak ? Yumuşak referanslar orada bir israf gibi görünüyor, çünkü bir anahtar nesneye artık güçlü bir şekilde ulaşılamadığında, hiç kimse bu eşlemeyi tekrar aramayacak.
Java'da altı tür nesne erişilebilirliği durumu:
Daha fazla ayrıntı için: https://www.artima.com/insidejvm/ed2/gc16.html «daralt
Zayıf bir şekilde atıfta bulunulan bir nesnenin yalnızca SADECE zayıf referansları olduğunda toplanacağının farkında olunmalıdır. Tek bir güçlü referansı varsa, ne kadar zayıf referansı olursa olsun toplanmaz.
Bir eylem içi bellek kullanımı özelliği vermek için, ağır nesneler altında Ağır nesneler ile Güçlü, Yumuşak, Zayıf ve Fantom referansları ile programın sonuna kadar saklayarak bir deneme yaptım. Daha sonra yığın kullanımı ve GC davranışı izlendi . Bu metrikler duruma göre değişebilir, ancak kesinlikle üst düzey bir anlayış sağlar. Aşağıda bulgular verilmiştir.
Ağır yük altında Yığın ve GC Davranışı
Bu deney için daha ayrıntılı grafikler, istatistikler ve gözlemler alabilirsiniz .
WeakReference : yalnızca zayıf başvurulan nesneler her GC döngüsünde (küçük veya dolu) toplanır.
SoftReference : yalnızca yumuşak başvurulan nesneler toplandığında şunlara bağlıdır:
-XX: SoftRefLRUPolicyMSPerMB = N bayrağı (varsayılan değer 1000, yani 1 saniye)
Yığındaki boş bellek miktarı.
Misal:
Daha sonra yalnızca SoftReference tarafından başvurulan nesne, en son erişildiği süre 10 saniyeden fazlaysa toplanır.