2012-03-20 11 views
29

मुझे उत्सुकता है कि fillInStackTracejava.lang.Throwable सार्वजनिक क्यों है?Throwable.fillInStackTrace() विधि सार्वजनिक क्यों है? कोई इसका इस्तेमाल क्यों करेगा?

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

लेकिन मुझे मौजूदा Throwable पर इस विधि को कॉल करने के लिए कोई भी उचित केस नहीं मिल रहा है। तो सवाल यह है कि: यह विधि सार्वजनिक क्यों है? क्या कोई समझ है?

उत्तर

36

प्रदर्शन का एक कारण है। अपवाद फेंकना और पकड़ना सस्ता है; महंगा हिस्सा filling in the stack trace है। यदि आप कुछ भी करने के लिए fillInStackTrace() ओवरराइड करते हैं, तो अपवाद भी सस्ता हो जाता है।

सस्ते अपवादों के साथ, आप flow control के लिए अपवादों का उपयोग कर सकते हैं, जो कुछ स्थितियों में कोड को और अधिक पठनीय बना सकते हैं; जब आप more advanced flow control की आवश्यकता होती है, तो आप उनका उपयोग कर सकते हैं, जहां आपको more advanced flow control की आवश्यकता होती है, और यदि आप actors library लिख रहे हैं तो वे उपयोगी हैं।

+0

यह दिलचस्प है, लेकिन अपवादों के माध्यम से प्रवाह को नियंत्रित करने के लिए जावा की फिर से अवधारणा नहीं है? –

+1

सामान्य हां में, लेकिन जैसा कि आप देख सकते हैं कि आप लिंक का पालन करते हैं, कभी-कभी यह बहुत उपयोगी होता है। – sbridges

+3

मुझे संदेह है कि यह उपयोग डिजाइनरों का इरादा था – Attila

4

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

+1

लेकिन उस मामले में क्यों स्टैक ट्रेस दिखाएं? –

+0

@lechlukasz - आपको * स्टैक ट्रेस दिखाने के लिए * नहीं है। कभी-कभी लॉग फ़ाइल को जांचने के लिए पर्याप्त होता है जहां सभी अपवाद मुद्रित होते हैं। बीटीडब्लू मैंने व्यक्तिगत रूप से कुछ संरक्षित आवेदन तोड़ दिया (केवल खेल के हित के लिए) और देखा कि उन्होंने इस चाल का उपयोग अतिरिक्त रूप से अपवित्रता के लिए किया था। – AlexR

18

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

यह rejected bug इंगित करता है कि आप इस विधि की आवश्यकता से उलझन में अकेले नहीं हैं।

1

एक समान question उत्तर प्रदान करता है।

जेएलएस के अनुसार, डिफ़ॉल्ट रूप से, अपवाद तत्काल होने पर स्टैकट्रैक भर जाता है। हालांकि, ऐसे समय होते हैं जब आप पुनर्स्थापना करते समय कुछ और उपयोगी स्थान पर स्टैक को "रीसेट" करना चाहते हैं।

इस कार्यक्षमता के लिए, हमने किया है fillInStackTrace()

संपादित

ठीक है, आज मुझे पता चला जावा मानक पुस्तकालय विनिर्देश संशोधन 1. के बाद JLS से हटा दिया गया था दूसरे की प्रस्तावना के रूप में संस्करण बताता है:

The specifications of the libraries are now far too large to fit into this volume, and 
they continue to evolve. Consequently, API specifications have been removed from 
this book. The library specifications can be found on the Web; this specification 
now concentrates solely on the Java programming language proper. 

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

Instances of two subclasses, Error and Exception, are conventionally used to indicate 
that exceptional situations have occurred. Typically, these instances are freshly 
created in the context of the exceptional situation so as to include relevant 
information (such as stack trace data). 

और java.lang.Throwable.printStackTrace() मेरी धारणा है कि इस वीएम कार्यान्वयन प्रदान करने के लिए अनुमति देने के लिए है

Prints this throwable and its backtrace to the standard error stream. 

है जो कुछ भी उनके संदर्भ के लिए सबसे अधिक प्रदर्शन/उपयुक्त कार्यान्वयन है। इस संदर्भ के साथ, स्पष्ट fillInStackTrace() सार्वजनिक होने से भी और अधिक समझ में आता है।

डिफ़ॉल्ट रूप से, वर्चुअल मशीन आपको इसके सर्वोत्तम प्रयास बैकट्रैक स्थान प्रदान करती है। FillInStackTrace() सार्वजनिक बनाना डेवलपर्स को और परिष्कृत करने की अनुमति देता है।

-

एक अंतिम संपादित करें :)

मैं relevant bits of the JLS First Edition करने के लिए एक शेष लिंक को ट्रैक करने में कामयाब रहे और मैं एक और कारण की पेशकश करने क्यों विधि सार्वजनिक है या नहीं। यह जावा में एक सामान्य स्पष्टीकरण बेहतर या बदतर है।

यह हमेशा इस तरह से किया गया था।

+0

क्या आप समझा सकते हैं कि इस प्रश्न के jtahlborn के जवाब से परे आपके लिंक के पीछे कौन सी अतिरिक्त जानकारी है? क्या जेएलएस 'fillInStackTrace' के उपयोग के बारे में कुछ भी बताता है? –

1

शायद आप एक अपवाद पकड़ना चाहते हैं और एक नया फेंकना चाहते हैं जो आपके पिछले अपवाद को समाहित नहीं करता है। पकड़े गए से GetStackTrace, और नए के लिए stackTrace सेट करें।

यह भी जब आप एक सिंगलटन अपवाद है काम करते हैं, की तरह एक बार instantiated होगा:

private static Exception theException = new MyException(); 

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

try { 
    .... 
} catch (OtherException oe) { 
    theException.fillStackTrace(oe.getStackTrace()); 
    theException.setMessage(...); //etc 
    throw theException; 
} 

स्थिर अपवाद का उपयोग करना मुश्किल हो सकता है अगर यह (धागे में यानी) समवर्ती कई बार फेंकी जा सकती है

+1

सबसे अच्छा, यह कोड obfuscation है। अपवादों का इलाज किया जाना चाहिए जैसे कि वे अपरिवर्तनीय थे। अन्य अपवाद को एक नए अपवाद के कारण के रूप में लपेटा जाना चाहिए। स्कैला गैर-स्थानीय प्रवाह नियंत्रण के लिए खाली स्टैक निशान का उपयोग करता है क्योंकि उसी कारण के लिए एक और उदाहरण मेरे पोस्ट में समझाया गया है, लेकिन ऐसा नहीं है। –

+0

अपवाद अपरिवर्तनीय नहीं हैं, इसलिए आप वास्तव में एक स्थिर को असाइन नहीं करना चाहते हैं। –

5

Throwable.fillInStackTrace() के लिए एक वैध उपयोग के मामले गैर स्थानीय नियंत्रण प्रवाह के लिए है:

उदाहरण के लिए, मेरे TrueZIP ढांचे के भीतर, मैं फाइल सिस्टम नियंत्रकों के लिए सजावट की एक जटिल श्रृंखला का उपयोग करता हूं। इस श्रृंखला में नियंत्रकों में से एक कक्षा FsLockController का एक उदाहरण है। यह ऑब्जेक्ट फ़ाइल सिस्टम के लिए एक ReentrantReadWriteLock के प्रबंधन के लिए ज़िम्मेदार है। अब इस श्रृंखला में कहीं भी एक फ़ाइल सिस्टम नियंत्रक गहराई से पता लगा सकता है कि एक लिखने-लॉक की आवश्यकता है, लेकिन FsLockController द्वारा केवल एक रीड-लॉक प्राप्त किया गया है। चूंकि आप रीड-लॉक को मृत-लॉकिंग के बिना एक लिखने-लॉक में अपग्रेड नहीं कर सकते हैं, इसलिए एक अपवाद फेंक दिया जाना चाहिए, जो कक्षा FsNeedsWriteLockException का उदाहरण होता है। सजावटी FsLockController तब इस अपवाद को पकड़ लेगा, रीड-लॉक जारी करेगा और फिर से ऑपरेशन को पुनः प्रयास करने से पहले लिखने-लॉक प्राप्त करेगा।

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

इस अपवाद प्रकार के बेस क्लास के लिए स्रोत कोड here देखा जा सकता है।

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