कोई StackTrace के साथ जावा में NullPointerException


333

मेरे पास हमारे जावा कोड के उदाहरण हैं NullPointerException, लेकिन जब मैं स्टैकट्रेस (जो मूल रूप से कॉलिंग समाप्त करता है Throwable.printStackTrace()) को लॉग इन करने की कोशिश करता हूं, तो मुझे लगता है:

java.lang.NullPointerException

क्या किसी ने इसे पहले देखा है? मैंने "जावा नल पॉइंटर खाली स्टैक ट्रेस" के लिए गुग्लिंग की कोशिश की, लेकिन ऐसा कुछ भी नहीं हुआ।


संदर्भ क्या है? क्या कई धागे शामिल हैं? मैं एक SwingWorker में एक अपवाद के ढेर का पता लगाने की कोशिश कर मुद्दों था।
माइकल मायर्स

यहां कोई थ्रेडिंग शामिल नहीं है, बस सादे पुराने जावा।
एडवर्ड स्टर्न

1
@Bozho - नहीं - निश्चित नहीं कि NullPointer को कैसे दोबारा तैयार किया जाए।
एडवर्ड स्टर्न


-XX:-OmitStackTraceInFastThrowडुबकी में अधिक जानकारी : stackoverflow.com/questions/4659151/…
वडज़िम

जवाबों:


407

आप शायद हॉटस्पॉट जेवीएम (मूल रूप से सन माइक्रोसिस्टम्स द्वारा, बाद में ओरेकल द्वारा खरीदा गया, ओपनजेडके का हिस्सा) का उपयोग कर रहे हैं, जो बहुत अधिक अनुकूलन करता है। स्टैक के निशान वापस पाने के लिए, आपको -XX:-OmitStackTraceInFastThrowजेवीएम के विकल्प को पास करना होगा ।

अनुकूलन यह है कि जब पहली बार कोई अपवाद (आमतौर पर NullPointerException) होता है, तो पूर्ण स्टैक ट्रेस मुद्रित होता है और JVM स्टैक ट्रेस (या शायद कोड का स्थान) को याद करता है। जब वह अपवाद अक्सर पर्याप्त होता है, तो स्टैक ट्रेस अब मुद्रित नहीं होता है, दोनों को बेहतर प्रदर्शन प्राप्त करने के लिए और समान स्टैक के निशान के साथ लॉग को बाढ़ नहीं करना है।

यह देखने के लिए कि यह हॉटस्पॉट जेवीएम में कैसे लागू किया जाता है, इसकी एक प्रति पकड़ें और वैश्विक चर की खोज करें OmitStackTraceInFastThrow। पिछली बार मैंने कोड (2019 में) को देखा था, यह फ़ाइल graphKit.cpp में था


1
पारितोषिक के लिए धन्यवाद। किसी भी विचार अगर इस विकल्प को पारित करने के लिए कोई छिपी हुई गौचे हैं (यह तब तक बहुत ही सहज लगता है जब तक कि मेरा आवेदन अपवादों का एक टन नहीं फेंकता)?
एडवर्ड स्टर्न

कोई छिपी हुई गोटियाँ नहीं हैं जिन्हें मैं जानता हूँ। जब आप हॉटस्पॉट स्रोत कोड को देखते हैं, तो आप देख सकते हैं कि यह विकल्प केवल एक ही स्थान पर उपयोग किया जाता है (graphKit.cpp)। और यह मुझे ठीक लगता है।
रोलैंड इलिग

34
मैंने सोचा कि मैं अतिरिक्त जानकारी जोड़ दूंगा
sharakan

1
मैं एक OpenJDK JVM, संस्करण 1.8.0u171 (डेबियन 9) चला रहा हूं, और यह -XX:-OmitStackTraceInFastThrowध्वज को भी स्वीकार करता है । मुझे अभी तक इस बात की पुष्टि नहीं करनी है कि ऐसा क्यों था कि मैं स्टैक-ट्रैस (जैसे, उपयोग कर e.printStackTrace) को प्रिंट करने में भी असफल रहा था , लेकिन इसकी संभावना बहुत अधिक है। मैंने इस खोज को दर्शाने के लिए उत्तर का विस्तार किया है।
क्रिस डब्ल्यू।

हमारे मामले में पहले 125 अपवादों में एक स्टैक ट्रेस था, और फिर लॉग फ़ाइलों के 3 घुमावों में से कोई भी नहीं था। यह उत्तर अपराधी को खोजने में बहुत मददगार था।
sukhmel

61

जैसा कि आपने एक टिप्पणी में उल्लेख किया है, आप log4j का उपयोग कर रहे हैं। मैंने (अनजाने में) एक जगह की खोज की थी जहाँ मैंने लिखा था

LOG.error(exc);

ठेठ के बजाय

LOG.error("Some informative message", e);

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

शायद यह वही है जो आप अनुभव कर रहे हैं?


+1: यह वर्णित व्यवहार की व्याख्या करेगा, और आप केवल एक ही व्यक्ति नहीं हैं जिन्होंने यह खोज की है :)
पीटर लैंग

4
हमारे पास वास्तव में एक मानक नीति है ऊपर दिए गए पहले फॉर्म (Log.error (exc);) का उपयोग न करने के लिए - हम हमेशा 2 पैरामीटर हस्ताक्षर का उपयोग करते हैं ताकि हम केवल कच्चे स्टैकट्रेस के बजाय लॉग में कुछ वर्णनात्मक विवरण जोड़ दें।
एडवर्ड स्टर्न

5
ज़रूर, लेकिन नीति का मतलब यह नहीं है कि इसे हमेशा सही तरीके से निष्पादित किया जाए! यह कम से कम उल्लेख के लायक था।
स्टीवन श्लैंस्कर

यह सच है, लेकिन इस मामले में ;-)
एडवर्ड स्टर्न

28

हमने अतीत में भी ऐसा ही व्यवहार देखा है। यह पता चला है कि, किसी पागल कारण के लिए, यदि कोड में कई बार एक ही जगह पर NullPointerException हुई, तो थोड़ी देर के बाद Log.error(String, Throwable)पूर्ण स्टैक के निशान सहित बंद हो जाएगा।

अपने लॉग में आगे पीछे देखने का प्रयास करें। आप अपराधी को ढूंढ सकते हैं।

संपादित करें: यह बग प्रासंगिक लगता है, लेकिन यह बहुत पहले तय हो गया था कि शायद इसका कारण नहीं है।


2
बग बंद है, लेकिन -XX: -OmitStackTraceInFastThrow ध्वज को अभी भी प्रदर्शन अनुकूलन को हल करने की आवश्यकता है।
जोशुआ गोल्डबर्ग

मैं इसे हाल ही में देख रहा हूं। किसी भी सुराग के रूप में यह क्या कारण हो सकता है, या इसे कैसे ठीक किया जाए? लॉगिंग सिस्टम दिनों के लिए हो सकता है, और वास्तविक कारण बाहर घुमाया जा सकता है, थकाऊ खोज के बीच कभी नहीं ...
पावेल वेसेलोव

5
पावेल, क्या आपने -XX:-OmitStackTraceInFastThrowजोशुआ द्वारा सुझाए गए जेवीएम झंडे को आजमाया है ? यह भी देखें stackoverflow.com/a/2070568/6198
मैट सोलनिट

1
यह हमारे लिए था। धन्यवाद।
एंड्रयू Cheong

20

यहाँ एक स्पष्टीकरण दिया गया है: हॉटस्पॉट ने उत्पादन में अपने स्टैक के निशान को खोने के अपवादों का कारण बना - और फिक्स

मैंने मैक ओएस एक्स पर इसका परीक्षण किया है

  • जावा संस्करण "1.6.0_26"
  • जावा (TM) एसई रनटाइम एनवायरनमेंट (बिल्ड 1.6.0_26-b03-383-11A511)
  • जावा हॉटस्पॉट (TM) 64-बिट सर्वर VM (बिल्ड 20.1-b02-383, मिश्रित मोड)

    Object string = "abcd";
    int i = 0;
    while (i < 12289) {
        i++;
        try {
            Integer a = (Integer) string;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

कोड के इस विशिष्ट टुकड़े के लिए, 12288 पुनरावृत्तियों (+ आवृत्ति?) की सीमा लगती है जहां जेवीएम ने उपदेशित अपवाद का उपयोग करने का निर्णय लिया है ...


10

exception.toString आपको StackTrace नहीं देता है, यह केवल रिटर्न देता है

इस फेंकने योग्य का एक संक्षिप्त विवरण। इसका परिणाम यह है:

* the name of the class of this object
* ": " (a colon and a space)
* the result of invoking this object's getLocalizedMessage() method

exception.printStackTraceइसके बजाय StackTrace को आउटपुट करने के लिए उपयोग करें ।


क्षमा करें, मैं अपने मूल पद से चूक गया। मैं इन्हें Log4J के माध्यम से लॉग कर रहा हूं, जो प्रिंटस्टैकट्रेस () का उपयोग करता है।
एडवर्ड स्टर्न

1
क्या आपने getStackTrace()यह सुनिश्चित करने के लिए उपयोग करने की कोशिश की है कि समस्या आपके लकड़हारे के साथ नहीं है?
पीटर लैंग

1
यदि आप log4j का उपयोग कर रहे हैं, तो लॉग विधि में तर्क के भाग के रूप में अपवाद भेजना सुनिश्चित करें। मैं उस के साथ एक उत्तर पोस्ट करूंगा।
रवि वलाऊ

@raviaw मान्य बिंदु! @ एडवर्ड स्टर्न: क्या आप इस बात की पुष्टि कर सकते हैं कि आप निश्चित रूप से log4j विधि के 2-arg फॉर्म का उपयोग कर रहे हैं? मुझे पता है कि आपने नीचे एक उत्तर में उल्लेख किया है कि ऐसा करना कंपनी की नीति है, लेकिन क्या आप पूरी तरह से सुनिश्चित हैं कि इस मामले में आप नीति का पालन कर रहे हैं?
करस्टेनफ

यह एक लंबा शॉट हो सकता है, लेकिन क्या यह संभव है कि अपवाद किसी तीसरे पक्ष के कोड में उत्पन्न हो? हो सकता है कि यह एक (खराब लिखा हुआ) अपवाद आवरण है, जिसका स्ट्रिंग () केवल लिपटे अपवाद का वर्ग नाम देता है, और जो अंतर्निहित स्टैक ट्रेस प्रदान करने में विफल रहता है। अपने कैच ब्लॉक में logger.info ("एक्सेप्शन क्लास =" + exc.class.getCanonicalName ()) जैसे कुछ डालने की कोशिश करें और देखें कि आपको क्या मिलता है।
कार्स्टनफ़

4

वैकल्पिक सुझाव - यदि आप ग्रहण का उपयोग कर रहे हैं, तो आप स्वयं NullPointerException पर एक ब्रेकपॉइंट सेट कर सकते हैं (डीबग परिप्रेक्ष्य में, "ब्रेकप्वाइंट" टैब पर जाएं और इसमें जो थोड़ा आइकन है उस पर क्लिक करें)

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


1

toString()केवल अपवाद नाम और वैकल्पिक संदेश देता है। मैं कॉल करने का सुझाव दूंगा

exception.printStackTrace()

संदेश डंप करने के लिए, या यदि आपको आवश्यक विवरण की आवश्यकता है:

 StackTraceElement[] trace = exception.getStackTrace()

ऊपर देखें - मुझे याद है - मैं प्रिंटस्टैकट्रेस () का उपयोग कर रहा हूं।
एडवर्ड स्टर्न

1

(आपका प्रश्न अभी भी स्पष्ट नहीं है कि आपका कोड कॉल printStackTrace()कर रहा है या यह लॉगिंग हैंडलर द्वारा किया जा रहा है।)

यहां कुछ संभावित स्पष्टीकरण दिए गए हैं कि क्या हो सकता है:

  • लकड़हारा / हैंडलर का उपयोग केवल अपवाद संदेश स्ट्रिंग को आउटपुट करने के लिए कॉन्फ़िगर किया गया है, पूर्ण स्टैक ट्रेस नहीं।

  • आपका एप्लिकेशन (या कुछ तृतीय-पक्ष लाइब्रेरी) लॉग LOG.error(ex);4j लॉगर विधि के उदाहरण के 2-तर्क फॉर्म के बजाय अपवाद का उपयोग कर रहा है ।

  • संदेश कहीं और से आ रहा है जहाँ आपको लगता है कि यह है; उदाहरण के लिए, यह वास्तव में कुछ थर्ड-पार्टी लाइब्रेरी विधि, या डीबग करने के पहले के प्रयासों से बचा हुआ कुछ यादृच्छिक सामान आ रहा है।

  • लॉग किए जा रहे अपवाद ने स्टैकट्रेस को अस्पष्ट करने के लिए कुछ तरीकों को अधिभारित किया है। यदि ऐसा है, तो अपवाद वास्तविक NullPointerException नहीं होगा, लेकिन NPE के कुछ कस्टम उप-प्रकार या यहां तक ​​कि कुछ असंबद्ध अपवाद भी होंगे।

मुझे लगता है कि अंतिम संभावित स्पष्टीकरण बहुत कम संभावना है, लेकिन लोग रिवर्स इंजीनियरिंग को "रोकने" के लिए इस तरह का काम करने पर कम से कम चिंतन करते हैं। बेशक यह केवल ईमानदार डेवलपर्स के लिए जीवन को मुश्किल बनाने में सफल होता है।


1

जब आप अपने प्रोजेक्ट में AspectJ का उपयोग कर रहे हैं, तो ऐसा हो सकता है कि कुछ पहलू स्टैक ट्रेस के अपने हिस्से को छिपाते हैं। उदाहरण के लिए, आज मेरे पास था:

java.lang.NullPointerException:
  at com.company.product.MyTest.test(MyTest.java:37)

मावेन की अचूक के माध्यम से परीक्षण चलाते समय यह स्टैक ट्रेस मुद्रित किया गया था।

दूसरी ओर, जब IntelliJ में परीक्षण चल रहा था, एक अलग स्टैक ट्रेस मुद्रित किया गया था:

java.lang.NullPointerException
  at com.company.product.library.ArgumentChecker.nonNull(ArgumentChecker.java:67)
  at ...
  at com.company.product.aspects.CheckArgumentsAspect.wrap(CheckArgumentsAspect.java:82)
  at ...
  at com.company.product.MyTest.test(MyTest.java:37)

0

यह अपवाद को आउटपुट देगा, केवल डिबग करने के लिए उपयोग करें आपको बेहतर अपवादों को संभालना चाहिए।

import java.io.PrintWriter;
import java.io.StringWriter;
    public static String getStackTrace(Throwable t)
    {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw, true);
        t.printStackTrace(pw);
        pw.flush();
        sw.flush();
        return sw.toString();
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.