2015-07-30 6 views
13

तर्कसंगत अनुप्रयोग डेवलपर (ग्रहण पर आधारित आरएडी) में, सॉफ्टवेयर विश्लेषक के तहत, मुझे एक कोड समीक्षा टिप्पणी (प्रदर्शन => मेमोरी सेक्शन) के तहत "अंत में फेंक स्टेटमेंट से बचें" कह रही है।अंततः एक प्रदर्शन समस्या को अवरुद्ध करने के अंदर एक अपवाद फेंक रहा है?

आखिरकार ब्लॉक के अंदर फेंक को परिभाषित करने से प्रदर्शन प्रभावित होता है?

enter image description here

यहाँ कोड का टुकड़ा है, हम पहले से ही अपवाद ट्रेस लॉग इन करने के कोड बदलने के लिए सुझाव दिया है और अपवाद नहीं है,

 } finally { 
     if (bufferedReader != null) { 
      try { 
       bufferedReader.close(); 
      } catch (final IOException ex) { 
       throw ex; 
      } 
     } 
    } 

मैं सिर्फ यह कैसे स्मृति और प्रदर्शन को प्रभावित कर सकता है सोच रहा था ?

+13

** पृथ्वी पर क्यों आप कभी भी 'आखिरकार' ब्लॉक में अपवाद फेंक देंगे? ** ऐसा मत करो। कभी। –

+4

यदि आपके पास दो ऑब्जेक्ट्स हैं जिन्हें क्लीनअप, 'ए' और' बी 'की आवश्यकता है, लेकिन' ए 'की सफाई पहले से ही अपवाद फेंकती है, तो' बी 'की अनुपलब्ध सफाई मेमोरी लीक बना सकती है ... लेकिन यह सिर्फ एक अनुमान है। आखिरकार ब्लॉक के अंदर अपवाद फेंकना अच्छा नहीं है लेकिन स्मृति मुद्दे मेरे लिए शीर्ष कारण नहीं होंगे। –

+1

http://stackoverflow.com/questions/481446/throws-exception-in-finally-blocks – brso05

उत्तर

-1

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

This आप जावा

+3

आखिरकार ब्लॉक ** हमेशा ** निष्पादित है, भले ही कोशिश ब्लॉक ** ** ** अपवाद फेंक दें। – hzpz

0

में कोशिश पकड़ने के अंत में अपवाद हैंडलिंग के बारे में अधिक जानने के लिए अंत में ब्लॉक आप को साफ करने के एक और तरीका गुजर वस्तु बी कॉल कर सकते हैं में मदद कर सकता है। और आप अंततः उस विधि में ब्लॉक को पकड़ने का प्रयास कर सकते हैं।

यह अच्छा है कि यदि आप प्रत्येक ऑब्जेक्ट ए & बी अलग-अलग तरीकों के लिए विधियों को साफ़ करते हैं, जिसमें आप अंततः ब्लॉक को पकड़ने का प्रयास करते हैं। आप वस्तुओं को साफ करने के लिए दोनों विधियों को कॉल कर सकते हैं। प्रत्येक वस्तु को साफ करने के अपवाद स्वतंत्र रूप से संभाले जाते हैं।

6

finally ब्लॉक से निकाला गया अपवाद try से फेंकने वाले किसी भी अपवाद को प्रतिस्थापित करेगा, और वास्तविक समस्या के बारे में जानकारी खो जाने की संभावना है।

के बाद से try-finally ब्लॉक इस मामले में एक IOException फेंकने के लिए अनुमति दी है, यहाँ इसे लिखने के लिए एक बेहतर तरीका है:

try (BufferedReader bufferedReader = Files.newBufferedReader(Paths.get("file.txt"))) { 
    /* Work with `bufferedReader` */ 
} 

यह स्वचालित रूप से पाठक को बंद करने पर ब्लॉक बाहर निकलता है, और अच्छी तरह से किसी भी जिसके परिणामस्वरूप अपवाद संभालती है, भले ही try ब्लॉक के अंदर कोड Throwable के "दमन" तंत्र का उपयोग करके पहले अपना अपवाद फेंकता है।

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

और, आप कई संसाधनों के साथ प्रयास कर सकते हैं; ये सभी बंद हो जाएंगे, और एकाधिक बंद अपवादों को दबाया जा सकता है।

यह मानता है कि आप फ़ाइल I/O का उपयोग कर रहे हैं, लेकिन वही "कोशिश-संसाधन" संरचना AutoCloseable (स्ट्रीम, एसक्यूएल ऑब्जेक्ट्स इत्यादि) लागू करने वाली किसी भी चीज़ पर काम करेगी।

+0

@ मार्कोटोपोलनिक आप सही हैं। मुझे लगता है कि मुझे सही जवाब मिल गया है, और मेरे अच्छे उदाहरण को बढ़ा दिया गया है (जो मुझे उम्मीद है कि संपादन से पहले भी बेवकूफ नहीं था)। – erickson

+2

अनुत्तरित क्या रहता है, प्रदर्शन पर असर कहां है। मुझे वास्तव में विश्वास है कि चेतावनी बस गलत है। –

+0

यह उत्तर संपादन के बाद मुझे समझ में आता है। मुझे लगता है कि यह इसे संभालने का एक शानदार तरीका है। @MarkoTopolnik। मैंने अपने जवाब में प्रदर्शन प्रश्न का उत्तर दिया। मुझे लगता है कि प्रदर्शन हिट न्यूनतम होने की संभावना है, लेकिन अजीब बात यह है कि अनिवार्य रूप से एक अपवाद को फिर से उखाड़ फेंक दिया गया है जिसे पहले ही फेंक दिया गया है, जब इसे पहली बार फेंक दिया गया है तो त्रुटि को संभालने से कम कुशल है। दूसरा मुद्दा यह है कि जब आप आखिरकार ब्लॉक में फेंकते हैं, तो मुझे लगता है कि आप आवश्यक सफाई को खत्म नहीं कर रहे हैं। – stubsthewizard

0

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

निष्पादन गिरावट के रूप में, एक अचूक दृष्टिकोण से, एक पकड़े गए अपवाद को पुनर्स्थापित करने से यह केवल इसे संभालने से स्पष्ट रूप से कम कुशल होता है।

एक विशिष्ट उदाहरण के रूप में जहां यह हानिकारक होगा, ऐसा कुछ मेरे सिर के ऊपर से दिमाग में आता है। यदि आपके पास अंततः ब्लॉक में क्लीनअप करने का एक और तरीका है, जैसे FileOutputStream.close(), और पहले व्यक्ति ने एक त्रुटि फेंक दी, तो दूसरा कभी नहीं चलाएगा, क्योंकि फेंक स्टेटमेंट ब्लॉक की प्रसंस्करण को समाप्त करता है। उस समय आप संसाधनों को लीक करेंगे।

तो, इसे समेटने के लिए, आखिरकार ब्लॉक में कोशिश/पकड़ ठीक है, लेकिन फेंक स्टेटमेंट के उपयोग से दक्षता के साथ-साथ अनपेक्षित परिणाम (मेमोरी लीक) के लिए टालना चाहिए।

1

आदर्श समाधान:

try (BufferedReader bufferedReader = ...) { 
    //do stuff 
} 

लेकिन शायद आप जावा 1.6 में कर रहे हैं:

BufferedReader bufferedReader = null; 
try{ 
    bufferedReader = ...; 
    //do stuff 
} finally { 
    if (bufferedReader != null) { 
    try { 
     bufferedReader.close(); 
    } catch (final IOException ex) { 
     logger.error("Problem while cleaning up.", ex); 
    } 
    } 
} 
3

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

दो कारण नहीं फेंकने के लिए:।

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

  • जब आपके सामान्य नियंत्रण का प्रवाह बंद होने पर अपवाद के लिए बाधित हो जाता है, तो आप कुछ अंतरण I/O गड़बड़ कर सकते हैं (जिसका आपके पास कोई नियंत्रण नहीं है और जिसने आपके व्यावसायिक तर्क को प्रभावित नहीं किया है) उपयोगी काम के कुछ टुकड़े को पूरा करने से रोकें (उदाहरण के लिए, यह वर्तमान लेनदेन को वापस लुढ़का सकता है)। यह इस बात पर निर्भर हो सकता है कि किस प्रकार का संसाधन शामिल है; हो सकता है कि कुछ मामला है जहां आप पूरी तरह से असफल हो सकते हैं अगर बंद साफ नहीं होता है, लेकिन कई सामान्य मामलों (जैसे जेडीबीसी) के लिए देखभाल करने का कोई अच्छा कारण नहीं है।

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

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