2008-09-16 11 views
24

मैं कैसे पता लगा सकता हूं कि मेरे आवेदन में किसी अपवाद को कहीं भी फेंक दिया गया है?जावा में वैश्विक रूप से एक अपवाद को कब फेंक दिया गया है, तो मैं कैसे पता लगा सकता हूं?

मैं अपने जावा डेस्कटॉप एप्लिकेशन में कहीं भी अपवाद फेंकने पर ऑटो-जादुई रूप से एक ईमेल भेजता हूं। मैं इस तरह से समझता हूं कि मैं और अधिक सक्रिय हो सकता हूं।

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

कोई सुझाव?

+0

जावा 7 या नए के साथ काम करते समय आप http://stackoverflow.com/questions/95767/how-can-i-catch-awt-thread-exceptions-in-java?lq=1 के उत्तरों की जांच करना चाहेंगे – Suma

उत्तर

34

आप संभावित रूप से किसी भी अपवाद पर मेल नहीं करना चाहते हैं। जेडीके में बहुत सारे कोड हैं जो आम तौर पर काम करने के लिए अपवादों पर निर्भर करते हैं। मुझे लगता है कि आप अधिक बेकार हैं अपरिचित अपवाद हैं। यदि आप अपवादों को पकड़ रहे हैं तो आपको वहां अधिसूचनाएं संभालना चाहिए।

डेस्कटॉप ऐप में (ईडीटी) और ईडीटी के बाहर इस बारे में चिंता करने के लिए दो स्थान हैं। ग्लोबली आप java.util.Thread.UncaughtExceptionHandler को लागू करने वाले वर्ग को पंजीकृत कर सकते हैं और इसे java.util.Thread.setDefaultUncaughtExceptionHandler के माध्यम से पंजीकृत कर सकते हैं। यह तब कहा जाएगा जब एक अपवाद स्टैक के नीचे तक नीचे चला जाता है और थ्रेड को थ्रेड या थ्रेड ग्रुप पर वर्तमान थ्रेड इंस्टेंस पर हैंडलर सेट नहीं किया गया है।

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

तो अगर आप क्या अपवाद थ्रेड परवाह नहीं है एक नमूना में हुई इस तरह दिखना हो सकता है:

class ExceptionHandler implements Thread.UncaughtExceptionHandler { 
    public void uncaughtException(Thread t, Throwable e) { 
    handle(e); 
    } 

    public void handle(Throwable throwable) { 
    try { 
     // insert your e-mail code here 
    } catch (Throwable t) { 
     // don't let the exception get thrown out, will cause infinite looping! 
    } 
    } 

    public static void registerExceptionHandler() { 
    Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler()); 
    System.setProperty("sun.awt.exception.handler", ExceptionHandler.class.getName()); 
    } 
} 

कुछ यादृच्छिक पैकेज में इस वर्ग के जोड़े, और फिर registerExceptionHandler विधि कॉल और आप तैयार हो जाना चाहिए जाना।

+0

अच्छा! कोड के लिए धन्यवाद। –

+2

आपको अंतिम पंक्ति System.setProperty ("sun.awt.exception.handler", ExceptionHandler.class.getName()) की आवश्यकता क्यों है; यह इस लाइन के बिना काम कर रहा है। और सूर्य। यह अनुमान लगाता है कि सूरज के कार्यान्वयन के लिए विशिष्ट हो सकता है। – feiroox

+1

यदि इवेंट डिस्पैच थ्रेड के अंदर अपवाद फेंक दिया गया है। स्विंग/एडब्ल्यूटी ईडीटी के पास अपने धागे की जड़ पर अपना अपवाद कैचर है और यह इसमें हुक है। – shemnon

0

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

5

जावा 1.5 में नए डिबगिंग हुक आपको ऐसा करने देते हैं। यह उदा। सक्षम बनाता है डिबगर्स में "किसी अपवाद पर तोड़ें"।

Here's the specific Javadoc आपको चाहिए।

4

Thread.UncaughtExceptionHandler देखें। आप पूरे वीएम के लिए इसे प्रति थ्रेड या डिफ़ॉल्ट एक सेट कर सकते हैं।

इससे कम से कम आपको याद करने में मदद मिलेगी।

0

यदि आप Spring जैसे वेब ढांचे का उपयोग कर रहे हैं तो आप अपने वेब.एक्सएमएल में किसी पृष्ठ पर प्रतिनिधि हो सकते हैं और फिर ईमेल भेजने के लिए नियंत्रक का उपयोग कर सकते हैं।

web.xml में: उदाहरण के लिए:

<error-page> 
    <error-code>500</error-code> 
    <location>/error/500.htm</location> 
</error-page> 

फिर एक नियंत्रक के रूप में /error/500.htm परिभाषित करते हैं। (String [

Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception"); 

तुम सिर्फ एक नियमित रूप से जावा प्रोग्राम चला रहे हैं, तो मैं कल्पना कर सकते हैं आप public static void मैं के साथ फंस रहे हैं: आप पैरामीटर javax.servlet.error.exception से अपवाद उपयोग कर सकते हैं ] args) {कोशिश {...} पकड़ (अपवाद ई) {}}

+0

वह उदाहरण किसी भी "WebApp" पर लागू होता है और इसका स्प्रिंग या वेब ढांचे के साथ कुछ लेना देना नहीं है। यह केवल बेजोड़ अपवादों पर लागू होता है जो आधार सर्वलेट वर्ग तक बुलबुला होता है, इस प्रकार http स्थिति 500 ​​उत्पन्न होता है - जो चाहता था (या नहीं) हो सकता है। – Cheekysoft

+0

आह, धन्यवाद - मुझे केवल वसंत के साथ अनुभव है इसलिए मैं बारी से बात नहीं करना चाहता था :) –

0

मुझे लगता है आप मतलब यह नहीं है किसी भी अपवाद बल्कि किसी भी ध्यान में न आया अपवाद।

यदि यह मामला है this article on the Sun Website में कुछ विचार हैं। आपको try-catch ब्लॉक में अपनी शीर्ष स्तरीय विधि को लपेटने की आवश्यकता है और अन्य थ्रेड को संभालने के लिए कुछ अतिरिक्त काम भी करना है।

0

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

+0

त्रुटियों और अपवादों के बीच अंतर को ध्यान में रखना उचित है। दोनों फेंकने योग्य हैं, लेकिन त्रुटियां अपवाद नहीं हैं क्योंकि वे भाई बहन हैं। – Cheekysoft

1

यदि आप जावा 1.3/1.4 का उपयोग कर रहे हैं, तो थ्रेड। UncaughtExceptionHandler उपलब्ध नहीं है। इस मामले में आप अपवाद फेंकने पर कुछ कोड ट्रिगर करने के लिए AOP के आधार पर समाधान का उपयोग कर सकते हैं। वसंत और/या पहलूजे सहायक हो सकता है।

1

मेरी वर्तमान परियोजना में मुझे त्रुटियों का पता लगाने के संबंध में समान आवश्यकता का सामना करना पड़ा। इस उद्देश्य के लिए मैंने निम्नलिखित दृष्टिकोण लागू किया है: मैं अपने ऐप में लॉगिंग के लिए log4j का उपयोग करता हूं, और हर जगह, जहां अपवाद पकड़ा जाता है, मैं मानक चीज करता हूं: log.error("Error's description goes here", e);, जहां ई अपवाद को फेंक दिया जाता है (देखें log4j दस्तावेज के बारे में विवरण के लिए "लॉग" का प्रारंभिकरण)। क्रम त्रुटि का पता लगाने के लिए, मैं अपने खुद के appender, जो log4j AppenderSkeleton वर्ग फैली का उपयोग करें:

import org.apache.log4j.AppenderSkeleton; 
import org.apache.log4j.spi.LoggingEvent; 

public class ErrorsDetectingAppender extends AppenderSkeleton { 

    private static boolean errorsOccured = false; 

    public static boolean errorsOccured() { 
     return errorsOccured; 
    } 

    public ErrorsDetectingAppender() { 
     super(); 
    } 

    @Override 
    public void close() { 
     // TODO Auto-generated method stub 
    } 

    @Override 
    public boolean requiresLayout() { 
     return false; 
    } 

    @Override 
    protected void append(LoggingEvent event) { 
     if (event.getLevel().toString().toLowerCase().equals("error")) { 
      System.out.println("-----------------Errors detected"); 
      this.errorsOccured = true; 
     } 
    } 
} 

log4j विन्यास फाइल अभी-अभी चयनित लकड़हारा के लिए नए appender की एक परिभाषा और उसके attachement (शामिल करने के लिए है मेरे मामले में रूट):

log4j.rootLogger = OTHER_APPENDERS, ED 
log4j.appender.ED=com.your.package.ErrorsDetectingAppender 

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

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

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