5

तो, मैंने हाल ही में जावा में अंतिम विधि की खोज की है (यकीन नहीं है कि मैंने इसे पहले क्यों याद किया, लेकिन वहां है)। यह लगता है जैसे कि मैं जिन मुद्दों के साथ काम कर रहा हूं, उनके उत्तर का उत्तर हो सकता है, लेकिन मैं पहले कुछ और जानकारी प्राप्त करना चाहता था।जावा में अंतिम() कैसे काम करता है?

  1. यह एक अलग थ्रेड में जगह लेता है, सही:

    This describes the order of operations involving finalize and the JGC:

    सवालों की एक जोड़ी:

    ऑनलाइन, मैं इस चित्र कचरा संग्रहण और अंतिम रूप देने की प्रक्रिया को दर्शाता हुआ पाया?

  2. क्या होता है यदि मैं अंतिम रूप देने के दौरान एक नई वस्तु को तुरंत चालू करता हूं? क्या यह अनुमति है?
  3. क्या होता है यदि मैं एक स्थिर विधि को अंतिम रूप देने से कॉल करता हूं?
  4. क्या होता है यदि मैं ऑब्जेक्ट को अंतिम रूप देने के भीतर से नया संदर्भ स्थापित करता हूं?

मुझे लगता है मैं व्याख्या करनी चाहिए क्यों मैं इच्छुक हूँ। मैं एलडब्ल्यूजेजीएल के साथ बहुत काम करता हूं, और ऐसा लगता है कि अगर मैं ओपनजीएल संसाधनों को स्वचालित रूप से साफ करने के लिए जावा ऑब्जेक्ट्स को अंतिम रूप देने के लिए अंतिम रूप का उपयोग कर सकता हूं, तो मैं एपीआई के संदर्भ में कुछ वाकई अच्छी चीजें कर सकता हूं।

+2

यह आपके प्रश्न का सीधा जवाब नहीं है, लेकिन पता है कि अंतिम रूप देने के लिए कभी भी गारंटी नहीं दी जाती है, जो कि कई कारणों में से एक है जिसका उपयोग भारी रूप से नहीं किया जाता है। (संपादित करें: और यहां तक ​​कि यदि यह है, तो जावा-प्रबंधित मेमोरी में मेमोरी प्रेशर के कारण इसे कॉल किया जाएगा। इसका मतलब है कि यदि आप इसे अन्य संसाधनों को मुक्त करने के लिए उपयोग करने का प्रयास कर रहे हैं, तो आप उनमें से बाहर हो सकते हैं और आपके प्रोग्राम क्रैश होने के बावजूद क्लीनअप उन सभी को पुनः प्राप्त कर सकता है, सिर्फ इसलिए कि जावा को पता नहीं है कि जीसी चलाने से पुनः दावा होगा (उदाहरण के लिए) फ़ाइल हैंडल।) – jacobm

उत्तर

3

मुझे नहीं लगता कि थ्रेड का उपयोग करने के बारे में कोई गारंटी है। नई वस्तुओं को तत्काल किया जा सकता है और स्थैतिक तरीकों को बुलाया जा सकता है। आपके ऑब्जेक्ट में एक नया संदर्भ स्थापित करने से इसे कचरा इकट्ठा करने से रोका जा सकता है, लेकिन finalize विधि को फिर से कॉल नहीं किया जाएगा - आप यह नहीं करना चाहते हैं।

संसाधनों की सफाई करना finalize विधि ठीक है, इसलिए आपको वहां अच्छा होना चाहिए। कुछ चेतावनियां, हालांकि:

विधि को कॉल करने की गारंटी नहीं है। यदि आपने संसाधनों को बांध लिया है जो आपके प्रोग्राम को पर रोकता है तो स्वचालित रूप से मुक्त नहीं किया जाएगा finalize पर निर्भर नहीं है।

जब विधि कहा जाता है तो इसकी गारंटी नहीं है। मेमोरी कसकर, यह जल्द ही होगा। बहुत सारी मुफ्त मेमोरी के साथ, अगर बाद में यह होगा। यह आपको ठीक कर सकता है: बहुत सारी यादों के साथ आप संसाधनों को मुक्त करने के बारे में चिंतित नहीं हो सकते हैं। (हालांकि उन्हें फांसी पर एक ही समय में चल रहे अन्य सॉफ्टवेयर के साथ हस्तक्षेप कर सकते हैं, जिस स्थिति में आप चिंतित होगा।)

मेरे ususal समाधान किसी तरह का निपटान कि स्वच्छ अप करता है विधि है । अगर मैं कर सकता हूं, और जैसे ही मैं कर सकता हूं, मैं इसे किसी बिंदु पर स्पष्ट रूप से कॉल करता हूं। फिर मैं एक अंतिम विधि जोड़ता हूं जो को विधि का निपटान करता है। (ध्यान दें कि निपटाने विधि अच्छी तरह से व्यवहार करना चाहिए जब जब एक से अधिक बार कहा जाता है! दरअसल, प्रोग्रामिंग इस तरह से मैं कॉल कर सकते हैं finalize बाहर निपटाने कई बार यकीन नहीं किया जा रहा है, तो पिछले कॉल सफलतापूर्वक और अभी तक चाहने किए गए थे इसे जितनी जल्दी हो सके प्रभावी ढंग से बुलाया जा सकता है।) अब, आदर्श रूप से, मेरे संसाधनों को मुक्त कर दिया जाता है जैसे ही मुझे उनकी आवश्यकता नहीं होती है।हालांकि, अगर मैं संसाधनों के साथ ऑब्जेक्ट का ट्रैक खो देता हूं, तो finalize विधि मेमोरी कम होने पर मुझे जमानत देगी और मुझे सहायता चाहिए।

5

अंतिम कचरा() जावा कचरा कलेक्टर द्वारा बुलाया जाता है जब यह पता चलता है कि उस विशेष वस्तु का कोई संदर्भ मौजूद नहीं है। अंतिमकरण() ऑब्जेक्ट क्लास के माध्यम से सभी जावा ऑब्जेक्ट्स द्वारा विरासत में मिला है।

जहां तक ​​मुझे पता है कि आपको अंतिम विधि() विधि I से स्थिर विधि कॉल करने में कोई कठिनाई नहीं होगी और आप इसे अंतिम रूप से() से एक नया संदर्भ स्थापित कर सकते हैं - हालांकि मैं कहूंगा कि यह खराब प्रोग्रामिंग अभ्यास है।

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

इसके अलावा, यह पूरी तरह से संभव है कि जीसी नहीं कहा जाएगा। इसलिए आप वास्तव में गारंटी गारंटी नहीं दे सकते हैं() को कभी भी कॉल किया जाएगा।

संसाधनों को साफ़ करें जब आप उनके साथ समाप्त हो जाएं, और इसे अंतिम रूप देने पर भरोसा न करें() यह मेरी सलाह है।

1

सबसे पहले, याद रखें कि अंतिम रूप से आपके सभी ऑब्जेक्ट्स के लिए अंतिम रूप भी चलाना होगा। आप इसे ऑब्जेक्ट से जुड़े देशी कोड में आवंटित मुक्त मेमोरी के लिए उपयोग कर सकते हैं, लेकिन शुद्ध जावा कोड के लिए अधिकांश उपयोग के मामले केवल संसाधनों की सफाई के "बैकअप" तंत्र को करने के लिए होते हैं। इसका मतलब है कि ज्यादातर मामलों में आपको संसाधनों को मैन्युअल रूप से मुक्त करना चाहिए और अंतिम रूप से इसे साफ करने के लिए फाइनलर्स केवल एक प्रकार का सहायक काम कर सकते हैं यदि आप इसे मानक तरीके से करना भूल जाते हैं। हालांकि, आप उन्हें सफाई के एकमात्र या मुख्य तंत्र के रूप में उपयोग नहीं कर सकते हैं। इससे भी आम तौर पर, आपको कोई भी कोड नहीं लिखना चाहिए जिसका शुद्धता अंतिम रूप से चलने वाले पर निर्भर करता है।

विज्ञापन 1।जहां तक ​​मुझे पता है, इस बात की कोई गारंटी नहीं है कि थ्रेड finalize() पर कॉल करता है, हालांकि व्यवहार में यह शायद जीसी धागे में से एक होगा।

विज्ञापन 2. नई वस्तुओं को इंस्टेंट करने की अनुमति है। हालांकि, अंतिम रूप में ऑब्जेक्ट संदर्भों को संभालने के साथ कई नुकसान हैं। विशेष रूप से, यदि आप किसी लाइव ऑब्जेक्ट में ऑब्जेक्ट को अंतिम रूप देने के लिए एक कठिन संदर्भ संग्रहीत करते हैं, तो आप अपने कचरे से एकत्रित वस्तु को साफ होने से रोक सकते हैं। इस तरह के ऑब्जेक्ट पुनरुत्थान से आपके संसाधनों को समाप्त हो सकता है यदि यह नियंत्रण से बाहर हो जाता है। साथ ही, finalize() में अपवादों के लिए देखें - वे अंतिम रूप को रोक सकते हैं, लेकिन आपके प्रोग्राम के बारे में जानने के लिए कोई स्वचालित तरीका नहीं है। आपको कोड को पकड़ने वाले ब्लॉक में लपेटने और स्वयं को जानकारी प्रसारित करने की आवश्यकता है। इसके अलावा, फाइनलाइजर्स के लंबे निष्पादन समय से ऑब्जेक्ट्स की कतार का निर्माण हो सकता है और बहुत सारी मेमोरी का उपभोग हो सकता है। this JavaWorld article में कुछ अन्य उल्लेखनीय समस्याओं और सीमाओं का वर्णन किया गया है।

विज्ञापन 3. अंतिमकर्ताओं से स्थैतिक तरीकों को कॉल करने के साथ कोई समस्या नहीं होनी चाहिए।

विज्ञापन 4. जैसा कि बिंदु 2 में उल्लिखित है, किसी ऑब्जेक्ट को अंतिमकरण के दौरान किसी अन्य लाइव ऑब्जेक्ट में संदर्भ डालकर एकत्रित कचरा (इसे पुनर्जीवित करने) से रोकना संभव है। हालांकि, यह मुश्किल व्यवहार है और शायद अच्छा अभ्यास नहीं है।

समेकित करने के लिए, आप अपने संसाधनों की सफाई के लिए अंतिमकर्ताओं पर भरोसा नहीं कर सकते हैं। आपको अपने मामले में मैन्युअल रूप से और फ़ाइनलाइज़र को संभालने की आवश्यकता है, कुछ डिग्री के लिए मैला कोडिंग के बाद कवर करने के लिए बैकअप तंत्र के रूप में सबसे अच्छा उपयोग किया जा सकता है। इसका मतलब है, दुर्भाग्यवश, ओपनजीएल संसाधनों को साफ करने के लिए अंतिमकर्ताओं का उपयोग करके एपीआई निसर बनाने का आपका विचार शायद काम नहीं करेगा।

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