Java'da hafızayı C'nin free()
işlevine benzer şekilde boşaltmanın bir yolu var mı ? Yoksa nesneyi null olarak ayarlamak ve tek seçenek GC'ye güvenmek mi?
Java'da hafızayı C'nin free()
işlevine benzer şekilde boşaltmanın bir yolu var mı ? Yoksa nesneyi null olarak ayarlamak ve tek seçenek GC'ye güvenmek mi?
Yanıtlar:
Java, yönetilen belleği kullanır, bu nedenle belleği new
ayırmanın tek yolu operatörü kullanmaktır ve belleği serbest bırakmanın tek yolu çöp toplayıcıya güvenmektir.
Bu bellek yönetimi teknik raporu (PDF), neler olduğunu açıklamaya yardımcı olabilir.
System.gc()
Çöp toplayıcının hemen çalışmasını önermek için de arayabilirsiniz . Ancak, nihai kararı kodunuz değil Java Runtime verir.
Göre Java belgeleri ,
Gc yönteminin çağrılması, Java Sanal Makinesi'nin şu anda kapladıkları belleği hızlı bir şekilde yeniden kullanılabilir hale getirmek için kullanılmayan nesneleri geri dönüştürmek için çaba harcadığını gösterir. Yöntem çağrısından kontrol geri döndüğünde, Java Sanal Makinesi, atılan tüm nesnelerden alan kazanmak için en iyi çabayı göstermiştir.
System.gc()
tamamen görmezden geldiği söylendi .
Hiç kimse null
, düşünmek isteyebileceğiniz hafızayı "serbest bırakmak" için meşru bir teknik olan nesne referanslarını açıkça belirtmekten bahsetmemiş gibi görünüyor .
Örneğin, List<String>
boyutu çok büyük olan, ancak yalnızca yöntemin yarısına kadar gerekli olan bir yöntemin başında bir ilan ettiğinizi varsayalım . Bu noktada List referansını null
, yöntem tamamlanmadan önce çöp toplayıcının bu nesneyi potansiyel olarak geri almasına izin verecek şekilde ayarlayabilirsiniz (ve referans yine de kapsam dışına düşer).
Bu tekniği gerçekte nadiren kullandığımı ancak çok büyük veri yapılarıyla uğraşırken dikkate almaya değer olduğunu unutmayın.
System.gc();
Çöp toplayıcıyı çalıştırır.
Gc yöntemin çağrılması anlaşılacağı bellek yapmak için kullanılmayan nesneleri geri dönüşüm doğru Java Virtual Machine expend çaba şu anda hızlı yeniden kullanılabilecektir işgal söyledi. Yöntem çağrısından kontrol geri döndüğünde, Java Sanal Makinesi, atılan tüm nesnelerden alan kazanmak için en iyi çabayı göstermiştir.
Tavsiye edilmez.
Düzenleme: Orijinal cevabı 2009'da yazdım. Şimdi 2015.
Çöp toplayıcıları, Java'nın yaklaşık 20 yılı içinde giderek daha iyi hale geldi. Bu noktada, çöp toplayıcıyı manuel olarak çağırıyorsanız, diğer yaklaşımları düşünmek isteyebilirsiniz:
* "Ben şahsen değişkenleri ileride düzgün bir şekilde silmek için bir yer tutucu olarak geçersiz kılmaya güveniyorum. Örneğin, dizinin kendisini fiilen silmeden (boş bırakmadan) önce bir dizinin tüm öğelerini geçersiz kılmak için zaman ayırıyorum."
Bu gereksizdir. Java GC'nin çalışma şekli, kendilerine referansı olmayan nesneleri bulmasıdır, bu nedenle, referansa (= değişken) a işaret eden bir Nesne x'e sahipsem, GC onu silmez, çünkü bir referans vardır. o nesneye:
a -> x
Eğer a'yı boş bırakırsanız, bu olur:
a -> null
x
Yani şimdi x'in kendisine işaret eden bir referansı yok ve silinecek. Aynı şey, a'yı x'ten farklı bir nesneye referans olarak ayarladığınızda da olur.
Dolayısıyla, x, y ve z nesnelerine başvuran bir dizi diziniz ve diziye başvuran bir a değişkenine sahipseniz, şöyle görünür:
a -> arr -> x
-> y
-> z
Eğer a'yı boş bırakırsanız, bu olur:
a -> null
arr -> x
-> y
-> z
Böylece GC, arr'ı kendisine referans set edilmemiş olarak bulur ve siler, bu da size şu yapıyı verir:
a -> null
x
y
z
Şimdi GC x, y ve z'yi bulur ve onları da siler. Dizideki her referansı sıfırlamak daha iyi bir şey yapmaz, koddaki CPU zamanını ve alanını kullanır (bu, bundan daha fazla zarar vermez. GC yine de olması gerektiği gibi çalışabilir. ).
Herhangi bir programdan (java ya da değil) bellek boşaltmayı istemenin geçerli bir nedeni, işletim sistemi düzeyinde diğer programlara daha fazla bellek sağlamaktır. Java uygulamam 250MB kullanıyorsa, onu 1MB’ye düşürmek ve 249 MB’ı diğer uygulamaların kullanımına açmak isteyebilirim.
Yiannis Xanthopoulos ve Hot Licks'in cevabını ve yorumunu genişletmek için (üzgünüm, henüz yorum yapamam!), Aşağıdaki örnek gibi VM seçeneklerini ayarlayabilirsiniz:
-XX:+UseG1GC -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=30
Benim jdk 7'mde, VM boştayken GC'den sonra yığının% 30'undan fazlası boş hale gelirse, kullanılmayan VM belleğini serbest bırakır. Muhtemelen bu parametreleri ayarlamanız gerekecek.
Aşağıdaki bağlantıda vurgulandığını görmemiş olsam da, bazı çöp toplayıcıların bu parametrelere uymayabileceğini ve birden fazla çekirdeğiniz olması durumunda varsayılan olarak java'nın sizin için bunlardan birini seçebileceğini unutmayın (bu nedenle yukarıdaki UseG1GC argümanı) ).
Güncelleme: Java 1.8.0_73 için JVM'nin zaman zaman varsayılan ayarlarla küçük miktarlar yayınladığını gördüm. Görünüşe göre, bunu yalnızca yığının ~% 70'i kullanılmamışsa yapıyor .. İşletim sisteminin fiziksel belleğinde düşük olsaydı daha agresif bir sürüm olup olmayacağını bilmiyorum.
Bunun üzerinde deneyler yaptım.
System.gc();
Yalnızca Çöp Toplayıcıyı çalıştırmayı önerdiği doğrudur .
Ancak , System.gc();
tüm referansları ayarladıktan sonra çağırmak null
, performansı ve hafıza kullanımını artıracaktır.
Gerçekten bir bellek bloğu tahsis etmek ve boşaltmak istiyorsanız, bunu doğrudan ByteBuffers ile yapabilirsiniz. Belleği boşaltmanın taşınabilir olmayan bir yolu bile var.
Bununla birlikte, önerildiği gibi, sadece C'de hafızayı boşaltmanız gerektiği için, bunu yapmak zorunda olmanın iyi bir fikir olduğu anlamına gelmez.
Ücretsiz () için gerçekten iyi bir kullanım durumunuz olduğunu düşünüyorsanız, lütfen bunu soruya ekleyin, böylece ne yapmak istediğinizi görebiliriz, büyük olasılıkla daha iyi bir yol vardır.
Tamamen javacoffeebreak.com/faq/faq0012.html adresinden
Düşük öncelikli bir iş parçacığı, kullanıcı için otomatik olarak çöp toplamayı halleder. Boşta kalma süresi sırasında, iş parçacığı çağrılabilir ve önceden Java'da bir nesneye tahsis edilmiş belleği boşaltmaya başlayabilir. Ancak endişelenmeyin - üstünüzdeki nesneleri silmez!
Bir nesneye herhangi bir referans olmadığında, çöp toplayıcı için adil bir oyun haline gelir. Bazı rutinleri çağırmak yerine (C ++ 'da ücretsiz olduğu gibi), nesneye yapılan tüm başvuruları null olarak atarsınız veya referansa yeni bir sınıf atarsınız.
Misal :
public static void main(String args[]) { // Instantiate a large memory using class MyLargeMemoryUsingClass myClass = new MyLargeMemoryUsingClass(8192); // Do some work for ( .............. ) { // Do some processing on myClass } // Clear reference to myClass myClass = null; // Continue processing, safe in the knowledge // that the garbage collector will reclaim myClass }
Kodunuz büyük miktarda bellek talep etmek üzereyse, düşük öncelikli bir iş parçacığı olarak bunu yapmasına izin vermek yerine, çöp toplayıcının alanı geri kazanmaya başlamasını isteyebilirsiniz. Bunu yapmak için, kodunuza aşağıdakileri ekleyin
System.gc();
Çöp toplayıcı, boş alanı geri kazanmaya çalışır ve uygulamanız, mümkün olduğu kadar çok bellek geri kazanılmış olarak çalışmaya devam edebilir (bellek parçalanması sorunları belirli platformlarda geçerli olabilir).
Benim durumumda, Java kodumun yakın gelecekte diğer dillere taşınması gerektiği için (Temelde C ++), en azından belleği düzgün bir şekilde boşaltmak için sözde hizmet vermek istiyorum, böylece daha sonra taşıma işlemine yardımcı olur.
Ben şahsen, gelecekte uygun şekilde silme işlemi için değişkenleri bir yer tutucu olarak geçersiz kılmaya güveniyorum. Örneğin, dizinin kendisini fiilen silmeden (boş bırakmadan) önce bir dizinin tüm öğelerini geçersiz kılmak için zaman ayırıyorum.
Ama benim durumum çok özel ve bunu yaparken performans hitleri aldığımı biliyorum.
* "Örneğin, boyutu çok büyük olacak şekilde büyüyen, ancak yalnızca yöntemin yarısına kadar gerekli olan bir yöntemin başlangıcında bir Liste ilan ettiğinizi varsayalım. Bu noktada List referansını null olarak ayarlayabilirsiniz. yöntem tamamlanmadan önce çöp toplayıcının bu nesneyi potansiyel olarak geri almasına izin vermek için (ve referans yine de kapsam dışında kalır). " *
Bu doğru, ancak bu çözüm genelleştirilemez. Bir List nesnesi başvurusunu null -will- çöp toplama için kullanılabilir hale getirirken, bu yalnızca ilkel türlerin List nesnesi için geçerlidir. List nesnesi bunun yerine başvuru türleri içeriyorsa, List nesnesinin = null ayarlanması, listedeki -herhangi- başvuru türlerinin başvurusunu kaldırmaz. Bu durumda, List nesnesinin = null olarak ayarlanması, çöp toplama algoritması nesnelerin sahipsiz kaldığını belirleyecek kadar akıllı olmadığı sürece, nesneleri çöp toplama için kullanılamayacak olan içerilen referans türlerini yetim bırakacaktır.
Althrough java otomatik çöp toplama bazen nesnenin ne kadar büyük bilmek ve ne kadar bunun programlama kullanılarak .Free bellek bırakılır isteyeceksiniz sağlar import java.lang;
ve Runtime r=Runtime.getRuntime();
kullanan bellek değerlerini elde etmek için mem1=r.freeMemory();
boş bellek çağrısına r.gc();
yöntem ve çağrıfreeMemory()
JAVA'nın tavsiyesi boş atamaktır
Gönderen https://docs.oracle.com/cd/E19159-01/819-3681/abebi/index.html
Artık ihtiyaç duyulmayan değişkenlere açık bir şekilde boş değer atamak, çöp toplayıcının belleğin güvenli bir şekilde geri kazanılabilen bölümlerini tanımlamasına yardımcı olur. Java, bellek yönetimi sağlasa da, bellek sızıntılarını veya aşırı miktarda bellek kullanımını engellemez.
Bir uygulama, nesne referanslarını serbest bırakmayarak bellek sızıntılarına neden olabilir. Bunu yapmak, Java çöp toplayıcısının bu nesneleri geri kazanmasını engeller ve kullanılan bellek miktarının artmasıyla sonuçlanır. Kullanımlarından sonra değişkenlere yapılan başvuruları açıkça geçersiz kılmak, çöp toplayıcının belleği geri kazanmasına izin verir.
Bellek sızıntılarını tespit etmenin bir yolu, profil oluşturma araçlarını kullanmak ve her işlemden sonra bellek anlık görüntülerini almaktır. Kararlı durumda sızıntısız bir uygulama, çöp toplama işlemlerinden sonra sabit bir aktif yığın belleği gösterecektir.