, şu programı tahsil edilemediğiUlaşılamıyor nesneler çöp beklentilerimin Karşı
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.List;
public class StackTest {
public static void main(String[] args) {
Object object1 = new Object();
Object object2 = new Object();
List<Object> objects = Arrays.asList(object1, object2);
WeakReference<Object> ref1 = new WeakReference<>(object1);
WeakReference<Object> ref2 = new WeakReference<>(object2);
for (Object o : objects) {
System.out.println(o);
}
objects = null;
object1 = null;
object2 = null;
System.gc();
System.gc();
System.gc();
System.out.println("ref1: " + ref1.get());
System.out.println("ref2: " + ref2.get());
}
}
hala GC-ed değildir object1
ve object2
anlam
ref1: [email protected]
ref2: [email protected]
yazdırır. Ancak, for
döngüsünü programdan kaldırırken, bu nesneler GC-ed ve program yazdırılıyor olabilir. Ayrı bir yönteme for
döngü taşıma
ref1: null
ref2: null
aynı etkiye sahiptir: nesneler programın sonunda GC-ed.
Olanlardan şüpheleniyorum, bu for
döngüsünün bu nesneleri yığında saklaması ve daha sonra bunları kaldırmamasıdır. Ve nesne yığın üzerinde hala mevcut olduğundan, GC-ed olamaz. (Ben gerçekten iyi değilim) bayt koduna baktığımızda
bu hipotezi destekler niteliktedir:
53: invokeinterface #6, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
58: astore 6
60: aload 6
62: invokeinterface #7, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
67: ifeq 90
70: aload 6
72: invokeinterface #8, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
77: astore 7
79: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
82: aload 7
84: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
87: goto 60
Ben astore
komutları görüyorum, ama bayt kodu nerede bir yer nokta olamazdı bunlar tekrar yığından kaldırılır.
Ancak, benim teoriyle iki sorunlar var: O bayt kodu anlaşılan kadarıyla
- , ben
object1
(object2
tarafından üzerine) yığından kaldırılır ve son sadece olduğunu umuyordum döngüde erişilen nesne (object2
) GC-ed değil. programının çıkışını değişmez
for (Object o : objects) { System.out.println(o); o = null; }
için
for
döngü değiştirme. Bunun, yığındaki nesneye yapılan referansı temizleyeceğini düşünürdüm.
Soru: herkes bu for
-loop bu nesneler GC-ed olamaz olmasını sağlar neden sağlam bir teorisi var? Benim teorimde birkaç boşluk var.
Bağlam: bu sorun NetBeans yöntemi NBTestCase#assertGC
göre biz bellek sızıntılarını tespit için kullanılan bir birim testler, karşılaşıldı . Bu assertGC
yöntemi, öbekte veya yığında hala bir nesne başvurulduğunda başarısız olur. Bizim testte
, biz kod biz for
-loop kaldırıldı kadar başarısız tuttu
@Test
public void test(){
List<DisposableFoo> foos = ...;
doStuffWithFoo(foos);
List<WeakReference<DisposableFoo>> refs = ...;
for(DisposableFoo foo : foos){
disposeFoo(foo);
}
foos = null;
assertGC(refs);
}
gibi var.
Zaten bir geçici çözümümüz var (for
-loop'u ayrı bir yönteme taşıyın), ancak orijinal kodumuzun neden çalışmadığını anlamak istiyorum.
Sadece "System.gc" yi çağırdığınızdan, ancak GC'nin gerçekleştiği anlamına gelmediğinden - ama emin olduğunuzu bildiğinizden eminim –
@ScaryWombat: Biliyorum. Gerçek kod, birkaç kez 'System.gc' ile çağrılarak tüm yığının birkaç kez doldurulmasını sağlar. Bunu basit tutmak için bu programdan kaldırdım. Sorunu, yayınlanan kodla tutarlı bir şekilde yeniden oluşturabileceğimi ve for döngüsünü kaldırmanın sürekli çalışmasını sağladığımı unutmayın. – Robin
Geleneksel döngü için –