How can I convert a stack trace to a string?

2018-12-31 19:17发布

What is the easiest way to convert the result of Throwable.getStackTrace() to a string that depicts the stacktrace?

28条回答
查无此人
2楼-- · 2018-12-31 19:49

if you are using java 8, try this

Arrays.stream(e.getStackTrace())
                .map(s->s.toString())
                .collect(Collectors.joining("\n"));

you can find the code for getStackTrace() function provided by Throwable.java as :

public StackTraceElement[] getStackTrace() {
    return getOurStackTrace().clone();
}

and for StackTraceElement, it providers toString as:

public String toString() {
    return getClassName() + "." + methodName +
        (isNativeMethod() ? "(Native Method)" :
         (fileName != null && lineNumber >= 0 ?
          "(" + fileName + ":" + lineNumber + ")" :
          (fileName != null ?  "("+fileName+")" : "(Unknown Source)")));
}

So just join the StackTraceElement with "\n"

查看更多
何处买醉
3楼-- · 2018-12-31 19:51

Here is a version that is copy-pastable directly into code:

import java.io.StringWriter; 
import java.io.PrintWriter;

//Two lines of code to get the exception into a StringWriter
StringWriter sw = new StringWriter();
new Throwable().printStackTrace(new PrintWriter(sw));

//And to actually print it
logger.info("Current stack trace is:\n" + sw.toString());

Or, in a catch block

} catch (Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    logger.info("Current stack trace is:\n" + sw.toString());
}
查看更多
孤独寂梦人
4楼-- · 2018-12-31 19:51

The clever sniping in the first set of comments was very amusing, but it really depends on what you are trying to do. If you don't already have the correct library, then 3 lines of code (as in D. Wroblewski's answer) is perfect. OTOH, if you already have the apache.commons library (as most large projects will), then Amar's answer is shorter. OK, it might take you ten minutes to get the library and install it correctly (less than one if you know what you're doing). But the clock is ticking, so you may not have the time to spare. Jarek Przygódzki had an interesting caveat--"If you don't need nested exceptions".

But what if I do need the full stack traces, nested and all? In that case, the secret is to use apache.common's getFullStackTrace (see http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html#getFullStackTrace%28java.lang.Throwable%29)

It saved my bacon. Thanks, Amar, for the hint!

查看更多
栀子花@的思念
5楼-- · 2018-12-31 19:51

Old question, but I would just like to add the special case where you don't want to print all the stack, by removing some parts you are not actually interested in, excluding certain classes or packages.

Instead of a PrintWriter use a SelectivePrintWriter:

// This filters out this package and up.
String packageNameToFilter = "org.springframework";

StringWriter sw = new StringWriter();
PrintWriter pw = new SelectivePrintWriter(sw, packageNameToFilter);
e.printStackTrace(pw);
String sStackTrace = sw.toString(); 
System.out.println(sStackTrace);

Where the SelectivePrintWriter class is given by:

public class SelectivePrintWriter extends PrintWriter {
    private boolean on = true;
    private static final String AT = "\tat";
    private String internal;

    public SelectivePrintWriter(Writer out, String packageOrClassName) {
        super(out);
        internal = "\tat " + packageOrClassName;
    }

    public void println(Object obj) {
        if (obj instanceof String) {
            String txt = (String) obj;
            if (!txt.startsWith(AT)) on = true;
            else if (txt.startsWith(internal)) on = false;
            if (on) super.println(txt);
        } else {
            super.println(obj);
        }
    }
}

Please note this class may be easily adapted to filter out by Regex, contains or other criteria. Also note it depends upon Throwable implementation details (not likely to change, but still).

查看更多
情到深处是孤独
6楼-- · 2018-12-31 19:53

My oneliner to convert stack trace to the enclosed multi-line string:

Stream.of(e.getStackTrace()).map((a) -> a.toString()).collect(Collectors.joining("\n", "[", "]"))

Easy to pass to the logger "as is".

查看更多
不再属于我。
7楼-- · 2018-12-31 19:53

Few options

  1. StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); String exceptionAsString = sw.toString();

  2. Using Google Guava lib String stackTrace = Throwables.getStackTraceAsString ( myException ) ;

  3. org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable)

查看更多
登录 后发表回答