जावा / एंड्रॉइड - एक पूर्ण स्टैक ट्रेस कैसे प्रिंट करें?


124

एंड्रॉइड (जावा) में मैं एक पूर्ण स्टैक ट्रेस कैसे प्रिंट कर सकता हूं? यदि मेरा अनुप्रयोग nullPointerException या किसी चीज़ से क्रैश होता है, तो यह एक (लगभग) पूर्ण स्टैक ट्रेस को प्रिंट करता है:

java.io.IOException: Attempted read from closed stream.
com.android.music.sync.common.SoftSyncException: java.io.IOException: Attempted read from closed stream.
    at com.android.music.sync.google.MusicSyncAdapter.getChangesFromServerAsDom(MusicSyncAdapter.java:545)
    at com.android.music.sync.google.MusicSyncAdapter.fetchDataFromServer(MusicSyncAdapter.java:488)
    at com.android.music.sync.common.AbstractSyncAdapter.download(AbstractSyncAdapter.java:417)
    at com.android.music.sync.common.AbstractSyncAdapter.innerPerformSync(AbstractSyncAdapter.java:313)
    at com.android.music.sync.common.AbstractSyncAdapter.onPerformLoggedSync(AbstractSyncAdapter.java:243)
    at com.google.android.common.LoggingThreadedSyncAdapter.onPerformSync(LoggingThreadedSyncAdapter.java:33)
    at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:164)
Caused by: java.io.IOException: Attempted read from closed stream.
    at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:148)
    at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:159)
    at java.util.zip.GZIPInputStream.readFully(GZIPInputStream.java:212)
    at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:81)
    at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:64)
    at android.net.http.AndroidHttpClient.getUngzippedContent(AndroidHttpClient.java:218)
    at com.android.music.sync.api.MusicApiClientImpl.createAndExecuteMethod(MusicApiClientImpl.java:312)
    at com.android.music.sync.api.MusicApiClientImpl.getItems(MusicApiClientImpl.java:588)
    at com.android.music.sync.api.MusicApiClientImpl.getTracks(MusicApiClientImpl.java:638)
    at com.android.music.sync.google.MusicSyncAdapter.getChangesFromServerAsDom(MusicSyncAdapter.java:512)
    ... 6 more

हालाँकि कभी-कभी, डीबगिंग उद्देश्यों के लिए, मैं एक पूर्ण स्टैक ट्रेस लॉग करना चाहता हूँ जहाँ से मैं कोड में हूँ। मुझे लगा कि मैं बस यही कर सकता हूं:

StackTraceElement trace = new Exception().getStackTrace();
Log.d("myapp", trace.toString());

लेकिन यह सिर्फ संकेतक को ऑब्जेक्ट को प्रिंट करता है ... क्या मुझे उन्हें प्रिंट करने के लिए सभी स्टैक ट्रेस तत्वों के माध्यम से पुनरावृति करना है? या वहाँ एक सरल विधि यह सब बाहर मुद्रित करने के लिए है?


1
आप इस विधि का उपयोग कर सकते हैं। Thread.currentThread ()। GetStackTrace () stackoverflow.com/questions/1069066/…
user2024270

जवाबों:


119

हस्ताक्षर के साथ सभी लॉग विधियों के ओवरराइड होते हैं (String tag, String msg, Throwable tr)

तीसरे पैरामीटर के रूप में एक अपवाद पारित करना आपको लॉगकैट में पूर्ण स्टैकट्रेस देना चाहिए।


5
FYI करें तीन-तर्क लॉग विधियाँ getStackTraceString()पर्दे के पीछे @Thomas द्वारा उल्लिखित विधि का उपयोग करती हैं।
फिलिप रीचर्ट

6
मैंने दो साल के लिए एंड्रॉइड विकसित किया है और पहले कभी इस पर ध्यान नहीं दिया है। आपका बहुत बहुत धन्यवाद।
आह तुआन

स्रोत कोड को देखते हुए, आप सही हैं @PhilippReichart। यहाँ AOSP 4.2.2_r1 पर Log.d का कोड है
एहतेश चौधरी

152

निम्नलिखित चाल करना चाहिए:

Log.d("myapp", Log.getStackTraceString(new Exception()));

ध्यान दें कि ...x moreअंत में स्टैक ट्रेस से किसी भी जानकारी को काट नहीं है:

(यह इंगित करता है) कि इस अपवाद के लिए स्टैक ट्रेस का शेष उस अपवाद के स्टैक ट्रेस के नीचे से फ़्रेम की इंगित संख्या से मेल खाता है जो इस अपवाद के कारण हुआ था ("एनक्लोजिंग" अपवाद)।

... या दूसरे शब्दों में, पहले अपवाद से x moreअंतिम xपंक्तियों के साथ बदलें ।


1
कहाँ getStackTraceString()से है? ग्रहण में नहीं दिखा? इसका हिस्सा नहीं है Throwableया Exception....
जेक विल्सन

9
"... 6 अधिक" अंत में किसी भी जानकारी को काट नहीं रहा है। यह आपको बता रहा है, बाकी स्टैक ट्रेस वही है जो शीर्ष अपवाद के लिए था। बस पहले अपवाद से अंतिम 6 लाइनों को देखें।
टॉमाज़

आपको शायद लॉगिंग लाइब्रेरी (उपयोग करके import android.util.Log;) को आयात करना होगा ।
डैन

10

Log.getStackTraceString (थ्रोएबल टी) का उपयोग करें। आप गहरी खुदाई करके लंबे समय तक स्टैक के निशान प्राप्त कर सकते हैं। उदाहरण के लिए:

try {
    ...
} catch(Exception e) {
    Log.d("Some tag", Log.getStackTraceString(e.getCause().getCause()));
}

से पुनर्प्राप्त http://developer.android.com/reference/android/util/Log.html#getStackTraceString%28java.lang.Throwable%29


Log.getStackTraceString()स्टैक ट्रेस लॉग नहीं करता है यह सिर्फ स्ट्रिंग के रूप में इसे वापस करता है। उपरोक्त कोड कुछ भी लॉग नहीं करेगा और यदि e.getCause()है तो NPE के साथ भी विफल हो जाएगा null
फिलिप रीचर्ट

9
private static String buildStackTraceString(final StackTraceElement[] elements) {
    StringBuilder sb = new StringBuilder();
    if (elements != null && elements.length > 0) {
        for (StackTraceElement element : elements) {
            sb.append(element.toString());
        }
    }
    return sb.toString();
}


// call this at your check point
Log.d(TAG, buildStackTraceString(Thread.currentThread().getStackTrace()));

6

आप इसका उपयोग कर सकते हैं:

public static String toString(StackTraceElement[] stackTraceElements) {
    if (stackTraceElements == null)
        return "";
    StringBuilder stringBuilder = new StringBuilder();
    for (StackTraceElement element : stackTraceElements)
        stringBuilder.append(element.toString()).append("\n");
    return stringBuilder.toString();
}

4

आप अपने ऐप कोड में किसी भी बिंदु पर स्टैक ट्रेस प्रिंट कर सकते हैं जैसे कि तरीकों का उपयोग करके Thread.dumpStack()

कृपया अधिक विवरण के लिए लिंक पर जाएं


2

पूर्ण स्टैकट्रेस प्राप्त करने के लिए आपको थ्रोबेबल ऑब्जेक्ट का उपयोग करने की आवश्यकता है।

try{
 // code here
}catch(Exception e){
    String exception = getStackTrace(e);
}

public static String getStackTrace(final Throwable throwable) {
     final StringWriter sw = new StringWriter();
     final PrintWriter pw = new PrintWriter(sw, true);
     throwable.printStackTrace(pw);
     return sw.getBuffer().toString();
}

Ref: https://stackoverflow.com/a/18546861


0

मैंने तेजी से अब एक पुनरावर्ती कार्य किया जो फेंकने योग्य और फेंकने योग्य हो जाएगा ।getCause ()।

ऐसा इसलिए है क्योंकि प्रत्येक "थ्रोएबल.गेटकॉज ()" आपके लिए एक नया अपवाद संदेश है जिसमें कुछ पंक्तियों को दोहराया गया है और नई लाइनें हैं। इसलिए अवधारणा यह है: यदि "कारण" है तो मुख्य फेंकने योग्य पर "n अधिक .." के साथ एक पंक्ति है, इसलिए मुझे "n more .." के साथ अंतिम पंक्ति मिलती है, तो मुझे कारण संदेश मिलता है और अंत में मैं अंतिम दोहराई जाने वाली पंक्ति (अंतिम पंक्ति जो दोनों पर दिखाई देती है: मुख्य फेंकने योग्य और कारण फेंकने योग्य है) के बाद केवल कारण वाले संदेश को प्रतिस्थापित करता हूं।

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

public static <T extends Throwable> String printStackTraceString(T ex) {     // Recursive
    Throwable tr = ex;
    if (tr != null) {
        String st = Log.getStackTraceString(tr);
        if (tr.getCause() != null) {
            // Recursion...
            String cs = printStackTraceString(tr.getCause());

            String r1 = st.subSequence(0x0, st.lastIndexOf("\n", st.lastIndexOf("\n") - "\n".length())).toString();
            String replace = r1.substring(r1.lastIndexOf("\n"));
            if (cs.contains(replace)) {
                return r1.concat(cs.subSequence(cs.indexOf(replace) + replace.length(), cs.length()).toString());
            }
        }
        return st;
    }
    return "";
}

मैंने इसे केवल 2 स्तर (मुख्य -> ​​कारण) के साथ आज़माया और अधिक के साथ नहीं: / यदि कुछ गलत है तो कृपया फ़ंक्शन को संपादित करें और एक टिप्पणी लिखें: D

एक अच्छा कोडिंग और एक अच्छा दिन भी है: डी

जरूरी:

इस कोड को कभी-कभी एक अपवाद मिलता है यदि "st" में "\ n" या समान नहीं होता है (मैंने पाया कि कुछ प्रकार के अपवादों में यह समस्या है)। इसे हल करने के लिए आपको कोड पंक्ति से पहले कुछ चेक जोड़ना होगा: "स्ट्रिंग r1 = ..."

आपको जांचने की आवश्यकता है: "st" में "\ n" शामिल है और "st.subSequence" का प्रारंभ और अंत अनुक्रमित दोनों मान्य हैं।

वैसे भी मैं इसे एक कोशिश के अंदर डालने और अपवाद के मामले में एक खाली स्ट्रिंग वापस करने का सुझाव देता हूं। (यह पुनरावर्ती है इसलिए लौटाए गए खाली स्ट्रिंग को पिछले संसाधित स्ट्रिंग के अनुरूप किया जाएगा)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.