How can I convert a stack trace to a string?

前端 未结 30 1172
再見小時候
再見小時候 2020-11-22 14:51

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

相关标签:
30条回答
  • 2020-11-22 15:11
     import java.io.PrintWriter;
    import java.io.StringWriter;
    
    public class PrintStackTrace {
    
        public static void main(String[] args) {
    
            try {
                int division = 0 / 0;
            } catch (ArithmeticException e) {
                StringWriter sw = new StringWriter();
                e.printStackTrace(new PrintWriter(sw));
                String exceptionAsString = sw.toString();
                System.out.println(exceptionAsString);
            }
        }
    }
    

    When you run the program, the output will be something similar:

    java.lang.ArithmeticException: / by zero
    at PrintStackTrace.main(PrintStackTrace.java:9)
    
    0 讨论(0)
  • 2020-11-22 15:13

    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).

    0 讨论(0)
  • 2020-11-22 15:13

    Warning: This may be a bit off topic, but oh well... ;)

    I don't know what the original posters reason was for wanting the stack trace as string in the first place. When the stack trace should end up in an SLF4J/Logback LOG, but no exception was or should be thrown here's what I do:

    public void remove(List<String> ids) {
        if(ids == null || ids.isEmpty()) {
            LOG.warn(
                "An empty list (or null) was passed to {}.remove(List). " +
                "Clearly, this call is unneccessary, the caller should " + 
                "avoid making it. A stacktrace follows.", 
                getClass().getName(),
                new Throwable ("Stacktrace")
            );
    
            return;
        }
    
        // actual work, remove stuff
    }
    

    I like it because it does not require an external library (other than your logging backend, which will be in place most of the time anyway, of course).

    0 讨论(0)
  • 2020-11-22 15:16

    an exapansion on Gala's answer that will also include the causes for the exception:

    private String extrapolateStackTrace(Exception ex) {
        Throwable e = ex;
        String trace = e.toString() + "\n";
        for (StackTraceElement e1 : e.getStackTrace()) {
            trace += "\t at " + e1.toString() + "\n";
        }
        while (e.getCause() != null) {
            e = e.getCause();
            trace += "Cause by: " + e.toString() + "\n";
            for (StackTraceElement e1 : e.getStackTrace()) {
                trace += "\t at " + e1.toString() + "\n";
            }
        }
        return trace;
    }
    
    0 讨论(0)
  • 2020-11-22 15:19

    Use Throwable.printStackTrace(PrintWriter pw) to send the stack trace to an appropriate writer.

    import java.io.StringWriter;
    import java.io.PrintWriter;
    
    // ...
    
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    e.printStackTrace(pw);
    String sStackTrace = sw.toString(); // stack trace as a string
    System.out.println(sStackTrace);
    
    0 讨论(0)
  • 2020-11-22 15:20

    One can use the following method to convert an Exception stack trace to String. This class is available in Apache commons-lang which is most common dependent library with many popular open sources

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

    0 讨论(0)
提交回复
热议问题