imprimir full java stack-trace tostring

java - full - ¿Cómo puedo convertir un seguimiento de pila en una cadena?



imprimir exception java (27)

¿Cuál es la forma más fácil de convertir el resultado de Throwable.getStackTrace() en una cadena que representa el seguimiento de pila?


Kotlin

Extender la clase Throwable le dará la propiedad String error.stackTraceString :

val Throwable.stackTraceString: String get() { val sw = StringWriter() val pw = PrintWriter(sw) this.printStackTrace(pw) return sw.toString() }



ADVERTENCIA: No incluye la causa (¡lo que suele ser el bit útil!)

public String stackTraceToString(Throwable e) { StringBuilder sb = new StringBuilder(); for (StackTraceElement element : e.getStackTrace()) { sb.append(element.toString()); sb.append("/n"); } return sb.toString(); }


Advertencia: Esto puede ser un poco fuera de tema, pero bueno ...;)

No sé cuál fue la razón original de los carteles para querer que la pila se trazara como una cadena en primer lugar. Cuando el seguimiento de la pila debe terminar en un SLF4J / Logback LOG, pero no se ha lanzado ninguna excepción o debería lanzarse, esto es lo que hago:

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 }

Me gusta porque no requiere una biblioteca externa (aparte de su backend de registro, que estará en su lugar la mayor parte del tiempo, por supuesto).


Aquí hay una versión que se puede copiar y pegar directamente en el código:

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

O bien, en un bloque catch.

} catch (Throwable t) { StringWriter sw = new StringWriter(); t.printStackTrace(new PrintWriter(sw)); logger.info("Current stack trace is:/n" + sw.toString()); }


Código de Apache Commons Lang 3.4 ( JavaDoc ):

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

La diferencia con las otras respuestas es que utiliza autoFlush en el PrintWriter .


El hábil ataque al primer grupo de comentarios fue muy divertido, pero realmente depende de lo que estés tratando de hacer. Si aún no tiene la biblioteca correcta, entonces 3 líneas de código (como en la respuesta de D. Wroblewski) son perfectas. OTOH, si ya tiene la biblioteca apache.commons (como la mayoría de los proyectos grandes), entonces la respuesta de Amar es más corta. De acuerdo, puede llevarle diez minutos obtener la biblioteca e instalarla correctamente (menos de uno si sabe lo que está haciendo). Pero el reloj no se detiene, por lo que es posible que no tenga tiempo de sobra. Jarek Przygódzki tuvo una advertencia interesante: "Si no necesita excepciones anidadas".

¿Pero qué pasa si necesito los rastros de pila completa, anidados y todo? En ese caso, el secreto es usar getFullStackTrace de apache.common (consulte http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html#getFullStackTrace%28java.lang.Throwable%29 )

Salvó mi tocino. Gracias, Amar, por la pista!


El siguiente código le permite obtener todo el stackTrace con un formato de String , sin usar API como log4J o incluso java.util.Logger :

catch (Exception e) { StackTraceElement[] stack = e.getStackTrace(); String exception = ""; for (StackTraceElement s : stack) { exception = exception + s.toString() + "/n/t/t"; } System.out.println(exception); // then you can send the exception string to a external file. }


Esto debería funcionar:

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


Impresión de la pila de seguimiento a la cadena

import java.io.PrintWriter; import java.io.StringWriter; public class StackTraceUtils { public static String stackTraceToString(StackTraceElement[] stackTrace) { StringWriter sw = new StringWriter(); printStackTrace(stackTrace, new PrintWriter(sw)); return sw.toString(); } public static void printStackTrace(StackTraceElement[] stackTrace, PrintWriter pw) { for(StackTraceElement stackTraceEl : stackTrace) { pw.println(stackTraceEl); } } }

Es útil cuando desea imprimir el seguimiento actual de la pila de hilos sin crear la instancia de Throwable , pero tenga en cuenta que crear un nuevo Throwable y obtener un seguimiento de la pila desde allí es en realidad más rápido y económico que llamar a Thread.getStackTrace .


Imprima el seguimiento de pila en un PrintStream, luego conviértalo en una cadena

// ... catch (Exception e) { ByteArrayOutputStream out = new ByteArrayOutputStream(); e.printStackTrace(new PrintStream(out)); String str = new String(out.toByteArray()); System.out.println(str); }


Inspirado por @Brian Agnew:

public static String getStackTrace(Throwable t) { StringWriter sw = new StringWriter(); t.printStackTrace(new PrintWriter(sw)); return sw.toString(); }


La solución es convertir el stacktrace de la matriz en un tipo de datos de cadena . Vea el siguiente ejemplo:

import java.util.Arrays; try{ }catch(Exception ex){ String stack = Arrays.toString(ex.getStackTrace()); System.out.println("stack "+ stack); }


Mi oneliner para convertir el seguimiento de pila a la cadena de multilínea adjunta:

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

Fácil de pasar al registrador "tal cual".


Para mí la forma más limpia y fácil fue:

import java.util.Arrays; Arrays.toString(e.getStackTrace());



Pregunta antigua, pero solo me gustaría agregar el caso especial en el que no desea imprimir toda la pila , eliminando algunas partes en las que no está realmente interesado, excluyendo ciertas clases o paquetes.

En lugar de un PrintWriter use un 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);

Donde la clase SelectivePrintWriter es dada por:

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

Tenga en cuenta que esta clase puede ser fácilmente adaptada para ser filtrada por Regex, contains u otros criterios. También tenga en cuenta que depende de los detalles de implementación de Throwable (no es probable que cambie, pero aún así).



Si está desarrollando para Android, una forma mucho más fácil es usar esto:

import android.util.Log; String stackTrace = Log.getStackTraceString(exception);

El formato es el mismo que getStacktrace, por ejemplo,

09-24 16:09:07.042: I/System.out(4844): java.lang.NullPointerException 09-24 16:09:07.042: I/System.out(4844): at com.temp.ttscancel.MainActivity.onCreate(MainActivity.java:43) 09-24 16:09:07.042: I/System.out(4844): at android.app.Activity.performCreate(Activity.java:5248) 09-24 16:09:07.043: I/System.out(4844): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread.access$800(ActivityThread.java:139) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210) 09-24 16:09:07.043: I/System.out(4844): at android.os.Handler.dispatchMessage(Handler.java:102) 09-24 16:09:07.043: I/System.out(4844): at android.os.Looper.loop(Looper.java:136) 09-24 16:09:07.044: I/System.out(4844): at android.app.ActivityThread.main(ActivityThread.java:5097) 09-24 16:09:07.044: I/System.out(4844): at java.lang.reflect.Method.invokeNative(Native Method) 09-24 16:09:07.044: I/System.out(4844): at java.lang.reflect.Method.invoke(Method.java:515) 09-24 16:09:07.044: I/System.out(4844): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 09-24 16:09:07.044: I/System.out(4844): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)


Si está utilizando Java 8, intente esto

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

Puede encontrar el código para la función getStackTrace () proporcionado por Throwable.java como:

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

y para StackTraceElement, se suministra a String como:

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

Tan solo únase al StackTraceElement con "/ n"


Si no desea utilizar una biblioteca externa y no está desarrollando para Android , puede crear un método de ''extensión'' como este:

public static String getStackTraceString(Throwable e) { return getStackTraceString(e, ""); } private static String getStackTraceString(Throwable e, String indent) { StringBuilder sb = new StringBuilder(); sb.append(e.toString()); sb.append("/n"); StackTraceElement[] stack = e.getStackTrace(); if (stack != null) { for (StackTraceElement stackTraceElement : stack) { sb.append(indent); sb.append("/tat "); sb.append(stackTraceElement.toString()); sb.append("/n"); } } Throwable[] suppressedExceptions = e.getSuppressed(); // Print suppressed exceptions indented one level deeper. if (suppressedExceptions != null) { for (Throwable throwable : suppressedExceptions) { sb.append(indent); sb.append("/tSuppressed: "); sb.append(getStackTraceString(throwable, indent + "/t")); } } Throwable cause = e.getCause(); if (cause != null) { sb.append(indent); sb.append("Caused by: "); sb.append(getStackTraceString(cause, indent)); } return sb.toString(); }


Sin java.io.* se puede hacer así.

String trace = e.toString() + "/n"; for (StackTraceElement e1 : e.getStackTrace()) { trace += "/t at " + e1.toString() + "/n"; }

Y luego la variable trace mantiene su seguimiento de pila. La salida también contiene la causa inicial, la salida es idéntica a printStackTrace()

Ejemplo, printStackTrace() produce:

java.io.FileNotFoundException: / (Is a directory) at java.io.FileOutputStream.open0(Native Method) at java.io.FileOutputStream.open(FileOutputStream.java:270) at java.io.FileOutputStream.<init>(FileOutputStream.java:213) at java.io.FileOutputStream.<init>(FileOutputStream.java:101) at Test.main(Test.java:9)

La cadena de trace mantiene, cuando se imprime a la stdout

java.io.FileNotFoundException: / (Is a directory) at java.io.FileOutputStream.open0(Native Method) at java.io.FileOutputStream.open(FileOutputStream.java:270) at java.io.FileOutputStream.<init>(FileOutputStream.java:213) at java.io.FileOutputStream.<init>(FileOutputStream.java:101) at Test.main(Test.java:9)


Use exp.printStackTrace() para mostrar la pila de su excepción.

try { int zero = 1 - 1; int a = 1/zero; } catch (Exception e) { e.printStackTrace(); }


Utilice Throwable.printStackTrace (PrintWriter pw) para enviar el seguimiento de la pila a un escritor apropiado.

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


una exapansión en la respuesta de Gala que también incluirá las causas de la excepción:

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


Arrays.toString(thrown.getStackTrace())

Es la forma más fácil de convertir el resultado en una cadena. Estoy usando esto en mi programa para imprimir el seguimiento de la pila

LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});


private String getCurrentStackTraceString() { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); return Arrays.stream(stackTrace).map(StackTraceElement::toString) .collect(Collectors.joining("/n")); }