Java’da hafızayı boşaltmanın bir yolu var mı?
free() işlev? Ya da nesneyi null olarak ayarlamak ve GC'ye tek seçeneğe güvenmek mi?
Java’da hafızayı boşaltmanın bir yolu var mı?
free() işlev? Ya da nesneyi null olarak ayarlamak ve GC'ye tek seçeneğe güvenmek mi?
Java, yönetilen belleği kullanır, böylece belleği ayırabilmenin tek yolu,
new operatör ve belleği ayırabilmenin tek yolu çöp toplayıcısına güvenmektir.
Bu bellek yönetimi (PDF) neler olduğunu açıklamaya yardımcı olabilir.
Ayrıca arayabilirsiniz
System.gc() Çöp toplayıcının hemen çalıştırıldığını önermek için. Ancak, Java Runtime kodunuzu değil, son kararı verir.
Göre Java belgeleri,
Gc yöntemini çağırmak şunu önerir: Java Sanal Makinesi harcama çabası Kullanılmayan nesneleri geri dönüşüme doğru hafıza yapmak için sipariş şu an için hızlı kullanılabilir yeniden kullanın. Kontrolden döndüğünde yöntem çağrısı, Java Sanal Makinesi geri almak için en iyi çabayı gösterdi tüm atılan nesnelerden alan.
Hiç kimse açıkça nesne başvuruları belirten söz etmiş gibi görünüyor
null, düşünmek isteyebileceğiniz "özgür" bellek için meşru bir tekniktir.
Örneğin, bir
List<String> büyüklüğünde büyüdüğü bir yöntemin başlangıcında, ancak büyük ölçüde yöntemin yarısına kadar gerekliydi. Bu noktada, List
null Çöp toplayıcının, yöntem tamamlanmadan önce bu nesneyi potansiyel olarak geri almasına izin vermek için (ve başvuru yine de kapsam dışıdır).
Bu tekniği nadiren kullandığımı fakat çok büyük veri yapılarıyla uğraşırken dikkate almam gerektiğini unutmayın.
System.gc();
Çöp toplayıcısını çalıştırır.
Gc yöntemini çağırmak anlaşılacağı Java Sanal Makinesinin, kullanılmakta olan nesneleri hızlı bir şekilde yeniden kullanmak için kullanabildikleri belleğe dönüştürmek amacıyla kullanılmayan nesneleri geri dönüştürmeye harcadığı çabası. Denetim, yöntem çağrısından döndüğünde, Java Virtual Machine tüm atılan nesnelerden alan kazanmak için en iyi çabayı göstermiştir.
Tavsiye edilmez.
Düzenleme: Orijinal yanıtı 2009'da yazdım. Şimdi 2015.
Çöp toplayıcıları ~ 20 yıl içinde sürekli olarak daha iyi bir hale geldi. Bu noktada, çöp toplayıcısını manuel olarak çağırıyorsanız, diğer yaklaşımları düşünmek isteyebilirsiniz:
* "Ben şahsen nulling değişkenleri gelecekteki uygun bir silme için bir yer tutucu olarak güveniyorum. Örneğin, ben aslında diziyi (null) silmeden önce bir dizinin tüm unsurları geçersiz kılmak için zaman ayırın."
Bu gereksizdir. Java GC'nin çalışma şekli, bunlara referans olmayan nesneler bulur, dolayısıyla bir referans (= değişken) ile bir Object x var ise, bu noktaya işaret eder, GC bunu silmez, çünkü bir referans vardır bu nesneye:
a -> x
Eğer bir null olursa, bu olur:
a -> null x
Yani şimdi x'in kendisine işaret eden bir referansı yok ve silinecek. Aynı şey, x'den farklı bir nesneyi referans olarak ayarladığınızda da olur.
Yani, x, y ve z nesnelerine başvurulan bir dizi arrınız varsa ve diziye başvuran bir değişkene benziyorsa:
a -> arr -> x -> y -> z
Eğer bir null olursa, bu olur:
a -> null arr -> x -> y -> z
Bu yüzden GC, kendisine hiçbir referans seti koymadığını ve silenize sahip olduğunu bulur:
a -> null x y z
Şimdi GC x, y ve z'yi bulur ve onları siler. Dizideki her bir referansı geçersiz kılmak, daha iyi bir şey yapmayacaktır, sadece CPU zamanını ve koddaki alanı kullanacaktır (bu, bundan daha fazla zarar vermeyeceğini söylemektedir. GC, yine de gereken şekilde çalışacaktır. ).
Herhangi bir programdan (java ya da değil) hafızayı boşaltmak için geçerli bir sebep, işletim sistemi seviyesinde diğer programlara daha fazla bellek sağlamaktır. Java uygulamam 250 MB kullanıyorsa, onu 1MB'a zorlamak ve 249MB'ı diğer uygulamalar için kullanılabilir hale getirmek isteyebilirim.
Bu konuda deney yaptım.
Olduğu doğru
System.gc(); Sadece Çöp Toplayıcısını çalıştırmayı önerir.
Ama aramak
System.gc(); tüm referansları ayarladıktan sonra
nullperformans ve hafıza işgalini geliştirecek.
Yiannis Xanthopoulos ve Hot Licks'in cevabını ve yorumunu genişletmek için (özür dilerim, henüz yorum yapamıyorum!), Bu örnek gibi VM seçeneklerini ayarlayabilirsiniz:
-XX:+UseG1GC -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=30
Benim jdk 7'de, VM boştayken GC'den sonra yığının% 30'undan daha fazla serbest kalırsa, bu kullanılmayan VM belleğini serbest bırakır. Bu parametreleri ayarlamanız gerekecektir.
Aşağıdaki bağlantıda vurgulanan görmedim, bazı çöp toplayıcıları bu parametrelere uymayabilir ve varsayılan olarak java sizin için bunlardan birini seçebilir, birden fazla çekirdeğe sahip olabilirsiniz (bu nedenle yukarıdaki UseG1GC argümanı) ).
Güncelleme: java 1.8.0_73 için JVM'nin, bazen varsayılan ayarlarla küçük miktarlar yayınladığını gördüm. Sadece yığının ~% 70'i kullanılmıyorsa bunu yapmak görünür. Eğer işletim sistemi fiziksel bellekte düşükse daha agresif bir sürüm olup olmayacağını bilmiyorum.
Gerçekten bir bellek bloğu ayırmak ve boşaltmak istiyorsanız, bunu doğrudan ByteBuffers ile yapabilirsiniz. Belleği boşaltmak için taşınabilir olmayan bir yol bile var.
Ancak, önerildiği gibi, sadece C'de hafızayı boşaltmanız gerektiğinden, bunu yapmak zorunda olmak iyi bir fikir değildir.
Eğer gerçekten iyi bir kullanım durumunuz olduğunu düşünüyorsanız (), lütfen soruya dahil edin, ne yapacağınızı görebilmemiz için, daha iyi bir yol olması muhtemeldir.
Düşük öncelikli bir iş parçacığı otomatik olarak çöp toplama ile ilgilenir kullanıcı için. Boşta kalma süresi boyunca, iş parçacığı üzerine çağrılabilir ve Java'da önceden bir nesneye ayrılmış belleği boşaltmaya başlayabilir. Ama endişelenme - senin üzerindeki nesnelerini silmez!
Bir nesneye referans olmadığında, bu oyun için adil bir oyun olur. çöp toplayıcı. Bazı rutinleri çağırmaktan ziyade C ++), yalnızca nesneye yapılan tüm referansları null olarak atarsınız veya referansa yeni bir sınıf atamak.
Örnek :
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 istemekse, çöp toplayıcısını alan yerine talep etmeye başlamak istiyor Düşük öncelikli bir iplik olarak bunu yapmaya izin vermekten daha fazla. Bunu yapmak için, ekle kodunuza aşağıdaki
System.gc();
Çöp toplayıcı, boş alanı geri almaya çalışacaktır. Uygulama, yeniden boyutlandırıldığı kadar bellekle yürütmeye devam edebilir Mümkün (belirli bölümlerde bellek parçalanması sorunları olabilir).