2010-03-12 12 views
25

Garbage Collection in Java hakkında this topic numaralı bir soruyu sordum. Ama aldığım cevap bana başka bir soru verdi.Java'da sınıflar çöp toplayıp ne zaman alınır?

Birisi, sınıfların çöp toplayıcı tarafından da alınabileceğini belirtti. Bu doğru mu?

Ve eğer doğruysa, bu nasıl çalışır?

+3

Bu konuyu faydalı bulabilirsiniz: http://stackoverflow.com/questions/453023/are-static-fields-open-for-garbage-collection –

+1

Bunlardan biri: "Bir java sınıf yükleyicisi ne zaman ve nasıl işaretlenir? çöp toplama için? " http://stackoverflow.com/questions/2344964/when-and-how-is-a-java-classloader-marked-for-garbage-collection – ewernli

cevap

29

Java'daki bir sınıf, hiçbir şey başvurmadığında çöp toplanabilir. Çoğu basit kurulumda bu asla olmaz, ancak meydana gelebileceği durumlar vardır. bu sınıfın

  • nesneler hala ulaşılabilir:

    bir sınıf ulaşılabilir hale ve dolayısıyla GC için uygun olmasını engellemek için birçok yol vardır. sınıfını temsil eden

  • Class nesne sınıfı hala erişilebilir yüklü ClassLoaderClassLoader tarafından yüklenen
  • diğer sınıfları hala ulaşılabilir
  • hala erişilebilir

yok olanların doğru olduğunda daha sonra ClassLoader ve yüklediği tüm sınıflar GC için uygundur.

İşte inşa örnek davranışlarda gerektiğini (kötü uygulamaların tamamını!): (Paketlemediyseniz!) x

Bir dizindeki bir derlenmiş dosyayı GCTester.class oluşturun. Bu var kaynak kodu:

 
in main 
Creating ClassLoader 
Loading Class 
Getting static field 
Reading static value 
[email protected] created 
Got value: [email protected] 
First gc() call 
Second gc() call (in main) 
[email protected] finalized 
End of main 

yılında:

import java.io.File; 
import java.net.URL; 
import java.net.URLClassLoader; 
import java.lang.reflect.Field; 

public class TestMe { 
    public static void main(String[] args) throws Exception { 
    System.out.println("in main"); 
    testGetObject(); 
    System.out.println("Second gc() call (in main)"); 
    System.gc(); 
    Thread.sleep(1000); 
    System.out.println("End of main"); 
    } 

    public static void testGetObject() throws Exception { 
    System.out.println("Creating ClassLoader"); 
    ClassLoader cl = new URLClassLoader(new URL[] {new File("./x").toURI().toURL()}); 
    System.out.println("Loading Class"); 
    Class<?> clazz = cl.loadClass("GCTester"); 

    System.out.println("Getting static field"); 
    Field field = clazz.getField("INSTANCE"); 

    System.out.println("Reading static value"); 
    Object object = field.get(null); 
    System.out.println("Got value: " + object); 

    System.out.println("First gc() call"); 
    System.gc(); 
    Thread.sleep(1000); 
    } 
} 

bu (veya benzeri) çıktı üretecektir TestMe Running:

public class GCTester { 
    public static final GCTester INSTANCE=new GCTester(); 

    private GCTester() { 
    System.out.println(this + " created"); 
    } 

    public void finalize() { 
    System.out.println(this + " finalized"); 
    } 
} 

Sonra x üst dizinine bir sınıf TestMe oluşturmak Son satırın ikincisi, GCTester örneğinin sonlandırıldığını görürüz, bu yalnızca sınıfın (ve ClassLoader) çöp toplama için uygundur.

+9

@Joachim Sauer: * finalize() * ifadesi sadece ispatlanır Bu durumda nesnenizin "ulaşılamaz" durumuna geçmesi, GCed olduğunu değil. KİS, kendi iradesiyle onu toplamakta ya da kullanmamakta hâlâ özgürdür: nihai sonucun çağrılması, nesnenin GCed olduğu anlamına gelmez. Eğer GCed olup olmadığını izlemek istiyorsanız, bir ReferenceQueue'da bir PhantomReference yazmanız ve o sıradaki anketi yapmanız gerekir. Ve yine de, nesnenin gerçekten de GCed olduğunu kanıtlamalısınız, bu sadece kendi sınıfını ve sınıf yükleyicisini (örneğinizde) GC için uygun, otomatik olarak GCed değil. – SyntaxT3rr0r

+0

@Wizard: Doğru, "GC için uygun olduğunu" söylemeliydim. –

+0

@JoachimSauer, “Sınıf” ın GC için uygun olmasını engelleyen 4 koşulu (4 puan) belirttiniz. Şimdi, 4 engeli temizlediğimizde bile, sistemin 'Class'ı toplamadığı hala mümkün mü? Temel olarak, JVM * JVM * 'nin "Sınıf" referansını vermemesi gerektiğini söyleyen JLS olduğunu ya da bir JVM *' nin söylemesi gerektiğini söylüyor - ** sonuçta *** bir "Sınıf" referansını vermiyor mu? – Pacerier

İlgili konular