2009-05-21 3 views
5

सिस्टम.gc() या अंतिम रूप() विधि कहलाते समय आंतरिक रूप से (JVM) क्या हुआ?System.gc() या अंतिम रूप() विधि कहलाते समय आंतरिक रूप से (JVM) क्या हुआ?

क्या यह वास्तव में कचरा इकट्ठा करता है या प्रदर्शन को कम करता है?

+1

बस ध्यान रखें कि जीसी व्यवहार कार्यान्वयन पर निर्भर है, इसलिए यह वीएम में बदल जाएगा। –

उत्तर

1

System.gc() का आह्वान करके कचरा कलेक्टर चलाया जाता है, जैसा कि नाम कहता है। इस बिंदु पर, जब वस्तुओं को वास्तव में हटाया जा रहा है, तो finalize() इन वस्तुओं पर गायब होने से पहले बुलाया जाता है।

अंतिम प्रश्न में "or" नहीं होना चाहिए। यह कचरा संग्रह और कम प्रदर्शन है।

आमतौर पर आपको gc पर ध्यान नहीं देना चाहिए क्योंकि यह आपके लिए वास्तव में अच्छा काम करता है। ऐसे उपयोग परिदृश्य हैं जहां आप समय पर एक निश्चित बिंदु पर कई वस्तुओं से छुटकारा पाना चाहते हैं; फिर यह व्यवहार्य है।

+13

System.gc() जरूरी नहीं है कि जीसी का आह्वान करें। यह केवल जेवीएम के लिए एक सुझाव है कि जीसी चलाने के लिए यह उचित समय है, लेकिन इसे चलाने का अंतिम निर्णय JVM तक है। – coobird

+0

मैं उन समयों की अपेक्षा करता हूं जब आप System.gc() को बहुत कम कहते हैं तो जीसी नहीं चलाया जाता है। दूसरी तरफ जीसी पूरी तरह से तभी चलाया जाता है जब थ्रेसहोल्ड पहुंच जाए। जीसी() को आम तौर पर आप पहले जीसी से पहले। –

+1

एक सिंगल सीपीयू के साथ, यदि आप System.gc() और साफ़ करने के लिए बहुत कुछ रखते हैं, तो आप क्लीनअप पूर्ण होने तक वास्तविक प्रदर्शन क्लिफ देख सकते हैं। यह वास्तव में दर्दनाक हो सकता है यदि आप अपने जेवीएम कार्य की मेमोरी छत के करीब भागते हैं और यह स्वचालित रूप से गंभीर जीसी करता है। लेकिन यदि आपके पास एकाधिक सीपीयू हैं तो प्रदर्शन समस्याएं बहुत कम हैं क्योंकि जीसी अन्य सीपीयू और आपके शेष जेवीएम चग्स के साथ मिलकर हो सकती है ... – jlarson

8

जब आप System.gc() पर कॉल करते हैं तो वास्तव में क्या होता है JVM निर्भर है। JVM इस कॉल को सुझाव के रूप में देखता है कि यह कचरा कलेक्टर चलाने के लिए एक अच्छा समय हो सकता है, इसलिए इस पर निर्भर न हों।

एक ऑब्जेक्ट की finalize() विधि कचरा कलेक्टर द्वारा किसी ऑब्जेक्ट पर चलती है जब JVM निर्धारित करता है कि उस ऑब्जेक्ट के लिए कोई और पहुंच योग्य संदर्भ नहीं है। आपको इसे अपने कोड में नहीं बुलाया जाना चाहिए। ध्यान रखें कि अंतिमकरण() उस समय बुलाया गया है जब आपका प्रोग्राम उस अंतिम संदर्भ को खो देता है, लेकिन भविष्य में जब कचरा कलेक्टर चलाया जाता है, तो समय पर एक विशिष्ट बिंदु पर होने पर निर्भर न करें (या बिल्कुल)।

0

अंतिमकरण() कचरा संग्रह के लिए ऑब्जेक्ट तैयार होने से ठीक पहले कोड का अंतिम बिट निष्पादित करने का माध्यम है (जब ऑब्जेक्ट का कोई मजबूत संदर्भ नहीं है)।

तो इसका उपयोग कब किया जाना चाहिए? केवल वर्तमान दो मामलों में:

  1. एक सुरक्षा के रूप में यह सुनिश्चित करें कि कुछ सेवा को बंद कर दिया जाता है या कुछ वांछित अंतिम परिवर्तन किया जाता है बनाने के लिए। उदाहरण के लिए I/O स्ट्रीम को बंद करने के लिए इनपुटस्ट्रीम क्लास का उपयोग करती है। उदाहरण के लिए आपने BufferedInputStream का उदाहरण बनाया है। इसका उपयोग करने के बाद मैन्युअल रूप से है() इसे बंद करने का मानना ​​है। लेकिन क्योंकि कोई ऐसा करना भूल सकता है, स्ट्रीम() स्ट्रीम को बंद करने के लिए सुरक्षा नेट के रूप में कार्य करता है।
  2. जबकि मूल का उपयोग कर। चूंकि कचरा कलेक्टर का मूल ऑब्जेक्ट्स पर कोई नियंत्रण नहीं है, इसलिए अंतिम() को पुनः प्राप्त करने के साधन के रूप में उपयोग किया जा सकता है।

उपर्युक्त दो मामलों के अलावा इसका कभी भी उपयोग नहीं किया जाता है। समझने के लिए क्यों? हमें किसी वस्तु के कार्य और जीवन चक्र को समझने की आवश्यकता है।

परिचय: एक अलग डिमन थ्रेड होता है जिसे फाइनलाइज़र थ्रेड कहा जाता है जो अंतिम() विधि को कॉल करने के लिए ज़िम्मेदार है। अंतिमकरण कतार क्यूई है जहां ऑब्जेक्ट्स को अंतिम रूप देने के लिए तैयार हैं() विधि रखी जाती है।

  1. जब ऑब्जेक्ट बनाया जाता है, तो JVM जांचता है कि ऑब्जेक्ट को अंतिम() विधि है या नहीं। यदि यह है तो यह आंतरिक रूप से नोट करता है कि इस विशेष वस्तु को अंतिम रूप दिया गया है() विधि।

जब एक वस्तु कचरा संग्रहण के लिए तैयार है, तो कचरा कलेक्टर धागा जांच करता है कि इस विशेष वस्तु को अंतिम रूप देने है() तालिका में उल्लेख से (1)।

  • 2 ए) यह तो यह कचरा संग्रहण के लिए भेज दिया जाता है नहीं करता है।

    2 बी) यह है, तो इसे अंतिमकरण कतार में जोड़ा जाता है। और यह तालिका (1) से वस्तु के प्रवेश को हटा देता है।

फ़ाइनलाइज़र थ्रेड कतार मतदान करता रहता है। कतार में प्रत्येक वस्तु के लिए, इसकी अंतिम() विधि को बुलाया जाता है। (2) से अंतिम() चक्र को कॉल करने के बाद फिर से दोहराया जाता है। यदि इस ऑब्जेक्ट में अभी भी कोई मजबूत संदर्भ नहीं है, तो जीसी के लिए भेजा गया है। यदि यह तो हमेशा (2 ए) कहा जाता है है, क्योंकि प्रवेश ऊपर चक्र के साथ (2 बी) मुद्दा

Basically finalize() method is only called once. 

तो क्या है में नष्ट कर दिया गया?

से (1)। ऑब्जेक्ट सृजन में इसका अतिरिक्त समय लगता है। जावा में मेमोरी आवंटन मॉलोक/कॉलोक इत्यादि की तुलना में 5x से 10x तेज है। तालिका में ऑब्जेक्ट को नोट करने की प्रक्रिया में प्राप्त हर समय खो जाता है। मैंने एक बार कोशिश की। लूप में 100000 ऑब्जेक्ट्स बनाएं और 2 मामलों में प्रोग्राम को समाप्त करने के लिए किए गए समय को मापें: कोई अंतिम रूप देने वाला नहीं है(), दूसरा अंतिम रूप देने के साथ()। यह 20% तेज पाया गया।

से (2 बी): मेमोरी रिसाव और भुखमरी। यदि कतार में ऑब्जेक्ट में बहुत सारे मेमोरी संसाधनों का संदर्भ है, तो उन सभी ऑब्जेक्ट्स को तब तक मुक्त नहीं किया जाएगा जब तक कि यह ऑब्जेक्ट जीसी के लिए तैयार न हो। अगर सभी ऑब्जेक्ट भारी वजन वस्तुएं हैं, तो वहां कमी हो सकती है।

से (2 बी): क्योंकि अंतिम() को केवल एक बार कहा जाता है, यदि teh finalize() में आपके "ऑब्जेक्ट" का एक मजबूत संदर्भ था। अगली बार ऑब्जेक्ट की फाइनली() को कभी नहीं कहा जाता है इसलिए वस्तु को असंगत स्थिति में छोड़ सकता है।

यदि अंतिम रूप में() एक अपवाद फेंक दिया गया है, तो इसे अनदेखा किया जाता है।

आपको नहीं पता कि अंतिम रूप से() को कॉल किया जाता है क्योंकि जीसी कहलाते समय आपके पास कोई नियंत्रण नहीं होता है। कभी-कभी ऐसा हो सकता है कि आप मान को अंतिम रूप देने में प्रिंट कर रहे हैं() लेकिन आउटपुट कभी नहीं दिखाया जाता है, क्योंकि आपके प्रोग्राम को अंतिम रूप देने के समय समाप्त हो सकता है() कहा जाता है।

इसलिए इसका उपयोग करने से बचें। इसके बजाए एक विधि बनाएं जिसका निपटान करें() जो आवश्यक संसाधनों को बंद कर देगा या अंतिम लॉग आदि के लिए the complete post on it। मुझे आशा है कि यह साफ़ हो जाएगा।

+0

स्टैक ओवरफ़्लो पसंद करता है कि आप अपने उत्तर में सामग्री प्रदान करते हैं, सिर्फ एक लिंक नहीं। यदि लिंक आपके उत्तर को तोड़ता है तो उसका कोई मूल्य नहीं होगा। –

+1

हो गया !! सुझाव के लिए धन्यवाद – Jatin

0

System.gc() स्मृति को साफ़ करता है, और व्यक्तिगत वस्तुओं से छुटकारा पाने के लिए अंतिम() का उपयोग करता है।

0

हाँ System.gc(); यदि आवश्यक हो तो अंतिम() विधि को ट्रिगर करेगा। सार्वजनिक वर्ग TestGarbageCollection {

public static void main(String[] args) { 
    while (true) { 
     TestClass s = new TestClass(); 
     s.display(); 
     System.gc(); 
    } 
} 

}

सार्वजनिक वर्ग TestClass {

public TestClass() { 
    System.out.println("constructor"); 
} 

public void display() { 
    System.out.println("display"); 
} 
@Override 
public void finalize() { 
    System.out.println("destructor"); 
} 

}

यह अंतिम रूप देने() विधि ट्रिगर किया जाएगा। चाहे आप स्थानीय वर्ग या ऑब्जेक्ट के अंतिम रूप को अंतिम रूप देने या अंतिम रूप देने की ओवरराइड ओवरराइड नहीं करेंगे।

+0

सच नहीं है !! यह JVM पर है कि कचरा संग्रह के दौरान अंतिम विधि को बुलाया जाना चाहिए या नहीं। और जावा-डॉक के अनुसार, 'System.gc' को कॉल करने से यह गारंटी नहीं मिलती है कि यह तुरंत मेमोरी फ्री-अप के लिए कचरा कलेक्टर को आमंत्रित करता है। यह सिर्फ सुझाव है !!! –

+0

@ अरुण कुमार: हालांकि ओरेकल System.gc() जावाडॉक्स कहते हैं: "इस विधि को कॉल करने से पता चलता है कि जावा वर्चुअल मशीन उन ऑब्जेक्ट्स को अंतिम रूप देने के लिए प्रयास करती है जिन्हें छोड़ दिया गया है लेकिन जिनके अंतिम तरीके अभी तक नहीं हुए हैं रन। ** जब विधि कॉल से नियंत्रण रिटर्न होता है, तो जावा वर्चुअल मशीन ने सभी उत्कृष्ट अंतिमकरण को पूरा करने के लिए सबसे अच्छा प्रयास किया है। ** "अंतिम वाक्य बहुत स्पष्ट है। और इससे पहले कि पानी पानी को धुंधला कर देता है। काश वे पहले से ही उन दस्तावेज़ों को ठीक करेंगे, क्योंकि अब मुझे नहीं पता कि क्या सोचना है। –

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