Java/Android-如何打印完整的堆栈跟踪?

Java/Android-如何打印完整的堆栈跟踪?,java,android,exception,stack,stack-trace,Java,Android,Exception,Stack,Stack Trace,在Android(Java)中,如何打印完整的堆栈跟踪?如果我的应用程序因nullPointerException或其他原因崩溃,它会打印(几乎)完整的堆栈跟踪,如下所示: java.io.IOException: Attempted read from closed stream. com.android.music.sync.common.SoftSyncException: java.io.IOException: Attempted read from closed stream.

在Android(Java)中,如何打印完整的堆栈跟踪?如果我的应用程序因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

但这只是打印出指向对象的指针。。。我必须遍历所有堆栈跟踪元素才能打印出来吗?或者有没有一种简单的方法可以将其全部打印出来?

有使用
(String tag、String msg、Throwable tr)
签名的所有覆盖


将异常作为第三个参数传递应该会在logcat中提供完整的stacktrace。

使用Log.getStackTraceString(Throwable t)。通过深入挖掘,可以获得更长的堆栈跟踪。例如:

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

中检索到的以下内容应能实现此目的:

Log.d("myapp", Log.getStackTraceString(new Exception()));
请注意,
…x更多

(这表示)此异常的堆栈跟踪的其余部分与由此异常引起的异常的堆栈跟踪底部指定的帧数相匹配(“封闭”异常)

…或者换句话说,用第一个异常中的最后一行替换
x更多

您可以使用:

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();
}

您需要使用Throwable对象来获取完整的堆栈跟踪

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:

您还可以使用
Thread.dumpStack()


请浏览

的链接,我现在快速完成了一个递归函数,它将迭代throwable和throwable.getCause()

这是因为每个“throwable.getCause()”都会向您返回一条新的异常消息,其中有一些重复的行和新行。 因此,这个概念是:如果有一个“原因”,那么在主throwable上有一行带有“n more..”,所以我在带有“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 "";
}
公共静态字符串printStackTraceString(tex){//Recursive
一次性tr=ex;
如果(tr!=null){
字符串st=Log.getStackTraceString(tr);
如果(tr.getCause()!=null){
//递归。。。
字符串cs=printStackTraceString(tr.getCause());
字符串r1=st.subSequence(0x0,st.lastIndexOf(“\n”,st.lastIndexOf(“\n”)-“\n”.length()).toString();
字符串替换=r1.子字符串(r1.lastIndexOf(“\n”);
如果(cs.包含(替换)){
返回r1.concat(cs.subSequence(cs.indexOf(replace)+replace.length(),cs.length()).toString());
}
}
返回st;
}
返回“”;
}
我只尝试了2级(主->原因),没有更多:/ 如果有任何错误,请编辑函数并写注释:D

祝你有一个愉快的编码和愉快的一天:D

重要: 如果“st”不包含“\n”或类似内容,此代码有时会出现异常(我发现某些类型的异常存在此问题)。 要解决这个问题,您需要在代码行之前添加一些检查:“stringr1=…”

您需要检查:“st”包含“\n”,并且“st.subSequence”的开始索引和结束索引都有效


无论如何,我建议将它放在一个try-catch中,并在出现异常时返回一个空字符串。(它是递归的,因此返回的空字符串将连接到先前处理的字符串).

FYI三种参数日志方法使用@Thomas在幕后提到的方法。我开发Android已经两年了,以前从未注意到这一点。非常感谢。看看源代码,是的@PhilippReichart。这是AOSP 4.2.2上的代码,其中
getStackTraceString()
from?没有出现在Eclipse中?它不是可丢弃的
异常的一部分,
…“…6更多”最后并没有切断任何信息。它告诉您,堆栈跟踪的其余部分与顶部异常相同。只需查看第一个异常的最后6行。您可能需要导入日志库(使用
import android.util.Log;
)。
Log.getStackTraceString()
不记录堆栈跟踪,它只是将其作为字符串返回。如果
e.getCause()
null
,则上述代码不会记录任何内容,并且在NPE中也会失败。您可以使用此方法Thread.currentThread().getStackTrace()可能重复
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();
}
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 "";
}