2010-03-12 11 views
25

मैंने this topic में जावा में कचरा संग्रह के बारे में एक प्रश्न पूछा। लेकिन मुझे जो जवाब मिला, उसने मुझे एक और सवाल दिया।जावा में कब और कैसे कक्षा कचरा एकत्रित किया जाता है?

किसी ने उल्लेख किया कि कक्षाएं भी कचरा कलेक्टर द्वारा एकत्र की जा सकती हैं। क्या यह सच है?

और यदि यह सत्य है, तो यह कैसे काम करता है?

+3

आपको यह विषय उपयोगी हो सकता है: http://stackoverflow.com/questions/453023/are-static-fields-open-for-garbage-collection –

+1

यह भी एक है: "जावा क्लासलोडर कब और कैसे चिह्नित किया जाता है कचरा संग्रह के लिए? " http://stackoverflow.com/questions/2344964/when-and-how-is-a-java-classloader-marked-for-garbage-collection – ewernli

उत्तर

29

जावा में एक कक्षा कचरा-संग्रहित हो सकती है जब कुछ भी इसका संदर्भ नहीं देता है। सबसे सरल सेटअप में यह कभी नहीं होता है, लेकिन ऐसी स्थितियां हैं जहां यह हो सकती है।

  • उस वर्ग की वस्तुओं अभी भी पहुंचा जा सकता है:

    वहाँ एक वर्ग पहुंच योग्य बनाने के लिए और इस प्रकार यह जीसी के लिए योग्य होने से रोकने के लिए कई तरीके हैं।

  • Class वस्तु वर्ग का प्रतिनिधित्व अभी भी पहुंचा जा सकता है
  • ClassLoader कि लोड वर्ग अभी भी पहुंचा जा सकता है
  • अन्य ClassLoader द्वारा लोड कक्षाएं अभी भी पहुंचा जा सकता है

जब कोई भी उन लोगों में से सत्य हैं , तो ClassLoader और लोड किए गए सभी वर्ग जीसी के लिए योग्य हैं।

यहाँ एक का निर्माण उदाहरण है कि व्यवहार का प्रदर्शन करना चाहिए (गलत व्यवहारों से भरा हुआ!):

एक निर्देशिका में बाईटकोड फ़ाइल GCTester.class बनाएँ (पैकेज नहीं!) x। यह स्रोत कोड है:

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); 
    } 
} 

TestMe चल रहा है इस (या समान) उत्पादन का उत्पादन होगा:

 
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 

में

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"); 
    } 
} 

फिर x की पेरेंट निर्देशिका में एक वर्ग TestMe बनाने पिछली पंक्ति में दूसरा हम देखते हैं कि GCTester उदाहरण को अंतिम रूप दिया गया है, जिसका अर्थ केवल वर्ग (और ClassLoader) कचरा संग्रह के लिए पात्र हैं।

+9

@ जोचिम सॉर: तथ्य यह है कि * अंतिम रूप() * केवल साबित होता है उस स्थिति में कि आपकी वस्तु "पहुंचने योग्य" स्थिति में चली जाती है, न कि यह जीसीड किया गया है। जीसी अभी भी इसे इकट्ठा करने के लिए स्वतंत्र है या नहीं, इसकी इच्छानुसार: तथ्य यह है कि अंतिम रूप दिया गया है इसका मतलब यह नहीं है कि वस्तु जीसीड की गई है। यदि आप ट्रैक करना चाहते हैं कि यह जीसीड किया गया है तो आपको उस कतार पर संदर्भक्यू और मतदान पर फ़ैंटॉम रेफरेंस डालना होगा। और फिर भी, आपको यह भी साबित करना चाहिए कि ऑब्जेक्ट वास्तव में जीसीड किया गया है, यह केवल अपनी कक्षा और क्लासलोडर (आपके उदाहरण में) बनाता है, जीसी के लिए पात्र है, स्वचालित रूप से जीसीड नहीं है। – SyntaxT3rr0r

+0

@ जादूगर: पर्याप्त सच है, मुझे यह कहना चाहिए था कि यह जीसी के लिए योग्य है "। –

+0

@ जोचिमसौयर, आपने 4 स्थितियों (4 अंक) बताए हैं जो 'कक्षा' को जीसी के योग्य होने से रोक देंगे। अब, जब हमने 4 बाधाओं को मंजूरी दे दी है, तब भी यह संभव है कि सिस्टम 'कक्षा' एकत्र न करे? असल में, मैं पूछ रहा हूं कि जेएलएस कह रहा है कि एक जेवीएम * * को गैर-संदर्भित 'कक्षा' जारी करना चाहिए या क्या यह एक जेवीएम * चाहिए - ** अंत में *** एक गैर-संदर्भित 'कक्षा' जारी करता है? – Pacerier

संबंधित मुद्दे