2012-09-17 7 views
5

में संसाधन लीक का पता लगाने के लिए अंतिम रूप से कार्यान्वित करने के लिए कैसे करें, मान लें कि मैंने संसाधन को साफ करने के लिए एक करीबी() विधि के साथ कुछ संसाधन वर्ग बनाया है, और मैं संसाधन को मुक्त करने के लिए अंतिम() प्रिंट करना चाहता हूं (और प्रिंट एक चेतावनी) अगर कोई करीबी() को कॉल करना भूल गया है। यह ठीक से कैसे किया जा सकता है?जावा

  • क्या यह केवल मूल (जेएनआई आवंटित) संसाधनों के लिए अनुशंसित है?
  • क्या होता है यदि आप किसी अन्य ऑब्जेक्ट के संदर्भ का उपयोग करते हैं जिसे अंतिम रूप दिया गया है, तो अंतिम रूप से? यदि चक्रीय निर्भरताएं हैं तो मुझे नहीं पता कि कचरा कलेक्टर आपको उन वस्तुओं तक पहुंचने से कैसे रोक सकता है जिनके अंतिमकर्ता निष्पादित किए जा सकते थे।
  • संसाधन लीक का पता लगाने और/या निपटने के लिए अंतिम() को ओवरराइड करने के लिए कोई बेहतर विकल्प हैं?
  • किसी भी अन्य नुकसान को अंतिम रूप देने के बारे में पता होना चाहिए?

नोट: मुझे पता है कि अंतिमकरण() का उपयोग करना आमतौर पर बुरा विचार है, और यह कहने की गारंटी नहीं है, इस पर चर्चा करने के कई अन्य प्रश्न हैं। यह प्रश्न विशेष रूप से जावा में फाइनलाइज़र को लागू करने के लिए के बारे में है, क्यों नहीं आपको (या नहीं होना चाहिए)।

+0

मुझे आशा है कि मेरे उत्तर मदद करेंगे। अगर मुझे कुछ याद आया तो मुझे बताएं। –

+0

अंतिम रूप से अंतिम रूप से अंतिमकृत वस्तुओं तक पहुंचने के बारे में दूसरे बिंदु को दोहराया। इसके बारे में अभी भी उत्सुक है कि इसका क्या प्रभाव होगा। – Soulman

उत्तर

4

effective java (2nd edition) में, यहोशू आइटम # 7 में विस्तार से बताता है कि आप यह कैसे कर सकते हैं। वह पहले सुझाव देता है कि आपको लगभग finalizer एस का उपयोग कभी नहीं करना चाहिए। हालांकि, इसका उपयोग केवल एक लॉग स्टेटमेंट मुद्रित करने का एक कारण है जिसमें कहा गया है कि आपके पास संसाधन रिसाव है। उनका कहना है कि ड्रॉ में से एक इस तरह से ऐसा करने का समर्थन करता है कि कोई आपकी कक्षा का विस्तार कर सकता है और सुपर फाइनलाइज़र को सही तरीके से कॉल नहीं कर सकता है। तो वह उपवर्ग में इस तरह कुछ करने के लिए पता चलता है:

// Manual finalizer chaining 
    @Override protected void finalize() throws Throwable { 
     try { 
      ... // Finalize subclass state 
     } finally { 
      super.finalize(); 
    } 
} 

यह सुनिश्चित करना है कि अगर कुछ वर्तमान कक्षा में टूट जाता है finally अभी भी कहा जाता हो जाएगा है। यह शायद एक खराब समाधान है क्योंकि यह उस व्यक्ति पर निर्भर करता है जो आपकी कक्षा को उप-वर्गीकृत कर रहा है। ऐसा करने के लिए एक वैकल्पिक समाधान एक अभिभावक ऑब्जेक्ट फ़ाइल का उपयोग करना है। ऐसा लगता है:

// Finalizer Guardian idiom 
    public class Foo { 
// Sole purpose of this object is to finalize outer Foo object 
     private final Object finalizerGuardian = new Object() { 
     @Override protected void finalize() throws Throwable { 
      ... // Finalize outer Foo object 
     } 
     }; 
     ... // Remainder omitted 
} 

यह एक क्लीनर दृष्टिकोण है क्योंकि आप जानते हैं कि कोई भी उस कार्यक्षमता को ओवरराइड नहीं कर सकता है।

संसाधनों को बंद करने का सुझाया गया तरीका अभी भी Closeable लागू कर रहा है और सुनिश्चित करें कि यह उपयोगकर्ता को बंद करने के लिए है। जैसा कि जोशुआ सुझाव देता है, आपको finalize विधि में किसी भी समय संवेदनशील संचालन नहीं करना चाहिए। JVM भविष्य में इसे कभी-कभी चलाने के लिए चुन सकता है। यदि आप काम करने या कुछ महत्वपूर्ण करने के लिए इस विधि के आधार पर हैं तो यह एक बुरा विचार है।

1

क्या यह केवल मूल (जेएनआई आवंटित) संसाधनों के लिए अनुशंसित है?

नहीं। आपका उपयोग केस अंतिम रूपकों के लिए मान्य है। मेरा मतलब संसाधन रिसाव लॉगिंग है।

क्या होता है यदि आप किसी अन्य जावा ऑब्जेक्ट को एक्सेस करते हैं जो को अंतिम रूप में अंतिम रूप दिया गया है?

यदि आप अभी भी इसे एक्सेस कर सकते हैं, तो इसे अंतिम रूप दिया नहीं गया है। या शायद मैं आपके प्रश्न में कुछ याद कर रहा हूँ।

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

के लिए अंतिमकरण() को ओवरराइड करने के लिए कोई बेहतर विकल्प है संसाधन संसाधनों का पता लगाने और/या निपटने के लिए?

मुझे लगता है कि अंतिम बातों का उपयोग करते समय सबसे महत्वपूर्ण बात यह है कि रिसाव के बारे में पता लगाने और लॉगिंग/चेतावनी नहीं है। और संसाधन रिसाव कचरा इकट्ठा करने से पहले इस रिसाव को लॉग करने का सबसे अच्छा क्षण है। तो फाइनलाइजर्स इसके लिए एक प्राकृतिक फिट हैं।

मैं इस पर दबाव डालना चाहता हूं: मैं प्रोग्रामर से निपटने के लिए अंतिमकर्ताओं का उपयोग नहीं करता जो संसाधन को बंद करना भूल गया था, लेकिन उसे सूचित करने के लिए कि उसे अपना कोड ठीक करने की आवश्यकता है।

किसी भी अन्य नुकसान को अंतिम रूप देने के बारे में पता होना चाहिए?

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

और अमीर रामिनफार द्वारा सुझाए गए अंतिम रूपकों के साथ किसी वस्तु को विरासत में रखते हुए देखभाल करें।

एक और बात: [FileInputStream][1] या [FileOutputStream][2] के स्रोत कोड पर एक नज़र डालें, वे उसी कारण से अंतिमकर्ताओं का उपयोग करते हैं।

+0

"अगर आप अभी भी इसका उपयोग कर सकते हैं, तो इसे अंतिम रूप दिया नहीं गया है। या शायद मुझे आपके प्रश्न में कुछ याद आ रही है।" लेकिन यदि ऑब्जेक्ट ए में ऑब्जेक्ट बी का संदर्भ है, और बी को ए से पहले अंतिम रूप दिया गया है, तो उसके अंतिमकर्ता से कोई एक्सेस बी नहीं हो सकता है? – Soulman

+0

मेरी पोस्ट संपादित की और उस प्रश्न को दोहराया। – Soulman

+0

अब मैं समझता हूं, उत्तर अपडेट किया गया। – dcernahoschi