Wie kann ich einen Stack-Trace in einen String konvertieren?

1502

Was ist der einfachste Weg, um das Ergebnis Throwable.getStackTrace()in eine Zeichenfolge zu konvertieren , die die Stapelverfolgung darstellt?

ripper234
quelle
6
Weil die Antwort von jqno tatsächlich die Throwable.getStackTrace () -Methode verwendet, die Sie in Ihrer Frage angegeben haben, während Brian dies nicht tut. Er verwendet stattdessen Throwable.printStackTrace ().
Stijn de Witt
10
Nahezu jedes Java-Projekt sollte Apache commons-lang enthalten. Es enthält viele praktische Methoden, die äußerst häufige Entwicklungsanforderungen implementieren.
Russell Silva
20
@StijndeWitt Diese drei Codezeilen müssen mit ziemlicher Sicherheit an der Stelle berücksichtigt werden, an der Sie sie aufgerufen haben. Da Sie nicht wissen, wo Sie sie ablegen sollen, werden sie zusammen mit allen anderen nützlichen Snippets in Ihrer Utility-Toolbox abgelegt. Bingo! Sie haben gerade Guave / Commons-Lang / Was auch immer neu erfunden ... nur nicht so gut. Importieren Sie stattdessen eine sinnvolle Dienstprogrammbibliothek und sparen Sie sich die Neuerfindung des Rads. Das wahre Zeichen eines Anfängers ist, dass Sie einen besseren Job machen können als die Autoren der Bibliothek.
Andrew Spencer
6
1. Guave hat - Throwables.getStackTraceAsString (e) 2. Apache Commons Lang - ExceptionUtils.getFullStackTrace 3. Schreiben Sie unsere eigenen benutzerdefinierten Methoden
user2323036
8
@ AndrewSpencer Ich verstehe nicht, warum ihr euch so sehr bemüht, StijndeWitt dafür zu verprügeln, dass ihr dies mit einem kleinen Ausschnitt erreichen wollt. Es ist wirklich nicht sehr gefährlich, eine winzige Utility-Methode zu schreiben (ich sehe es nicht als "SHEER ARROGANCE oh nooooo !! er denkt, er ist besser als Apache !!"). Es gibt Unmengen von Projekten, insbesondere in Nicht-Java-JVM-Sprachen, die Guava oder Commons Lang wirklich nicht einschließen möchten, nur um eine Stapelverfolgung zu protokollieren. Ich schreibe Scala & Clojure-Bibliotheken und werde Apache Commons Lang sicherlich nicht nur für eine Methode zu einer transitiven Abhängigkeit machen.
jm0

Antworten:

1039

Mit der folgenden Methode können Sie einen ExceptionStack-Trace in konvertieren String. Diese Klasse ist in Apache commons-lang verfügbar, der am häufigsten verwendeten abhängigen Bibliothek mit vielen gängigen Open Source-Quellen

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

amar
quelle
88
@Stijn - um fair zu sein (ich habe die aktuell am höchsten bewertete Antwort unten geschrieben), lohnt es sich, Commons-Lang für viel mehr Funktionalität zu betrachten
Brian Agnew
54
@StijndeWitt Commons Lang ist ziemlich häufig. Es ist bereits in den meisten meiner Projekte / Projekte bei der Arbeit vorhanden.
WhyNotHugo
16
@Hugo danke, wollte den StringWriter verwenden, um das Hinzufügen einer neuen Bibliothek zu vermeiden - es stellt sich heraus, dass es bereits eine Abhängigkeit von 3 meiner Abhängigkeiten ist. Überprüfen Sie im Übrigen, ob Sie es bereits haben.
Nathanial
33
@MartinAsenov - Nach Ihrer Logik würden Sie niemals eine solche Bibliothek verwenden, oder? Sie würden es nicht verwenden, wenn Sie es nicht bereits verwenden?
Brian Agnew
16
Zu Ihrer Information, das Paket hat sich geändert und die Klasse ist jetzt bei : org.apache.commons.lang3.exception.ExceptionUtils.
schmmd
2201

Verwenden Sie Throwable.printStackTrace(PrintWriter pw)diese Option , um den Stack-Trace an einen geeigneten Writer zu senden.

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);
Brian Agnew
quelle
505
Wenn Sie keine externe Bibliothek für so etwas Kleines und Einfaches einbinden möchten, verwenden Sie diese Antwort.
Stijn de Witt
8
Dadurch wird die Stapelverfolgung auf dieselbe Weise wie bei printStackTrace () gekürzt. Alle Ausnahmen im Stapel sind sichtbar, aber für jede Ausnahme kann der Stapel gekürzt werden. Jeder, der die gesamte Ablaufverfolgung benötigt, sollte dies berücksichtigen.
Laila Agaev
5
Wie sich herausstellt, ist dies ziemlich genau das, was die ExceptionUtils.getStackTrace () -Methode von Apache tut. Eigentlich fast auf den Brief.
Ticktock
6
@BrianAgnew, solltest du das StringWriterund nicht schließen PrintWriter?
Muhammad Gelbana
13
@BrianAgnew, danke für die Antwort. Es hat mich neugierig gemacht und hier ist, was ich gefunden habe: stackoverflow.com/questions/14542535/…
Muhammad Gelbana
459

Das sollte funktionieren:

StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
D. Wroblewski
quelle
69
Prägnant im Java-Kontext ist immer hügelig. Das printStackTracesollte nur eine Zeichenfolge zurückgeben und die Entscheidung darüber, ob sie gedruckt werden soll oder nicht, dem Benutzer
überlassen
35
printStackTrace Drucken in der Konsole ist akzeptabel, aber mindestens ein getStackTrace, das es als String zurückgibt, sollte standardmäßig verfügbar sein
Mateus Viccari
5
Welcher Teil davon ist prägnant? Sie müssen 2 Objekte erstellen, die für keinen anderen Zweck existieren, als die Stapelverfolgung in eine Zeichenfolge einzufügen.
ArtOfWarfare
7
@dmitry Eine aufgerufene Methode printXXX()sollte XXX drucken.
Marquis von Lorne
2
@ Greg Eigentlich war das nicht einmal Sarkasmus, es erforderte nur eine einfache Lektüre dessen, was er sagte.
Andrew
224

Wenn Sie für Android entwickeln, ist dies weitaus einfacher:

import android.util.Log;

String stackTrace = Log.getStackTraceString(exception); 

Das Format ist das gleiche wie bei getStacktrace, z

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)
Vicky Kapadia
quelle
2
Vielen Dank. In diesem Fall werden Datum und Tag nicht wie in printStackTrace () in jede Zeile geschrieben.
CoolMind
1
Tatsächlich verwendet Log.getStackTraceString in seinem Kern den oben erwähnten (D. Wroblewski) StringWriter und Printwriter.
MikeL
2
Der einfachste Weg, es einfach im Android-Protokoll zu drucken, ist: Log.e("TAG", "My message", new Throwable());
Erick M. Sprengel
113

WARNUNG: Enthält keine Ursache (was normalerweise das nützliche Bit ist!)

public String stackTraceToString(Throwable e) {
    StringBuilder sb = new StringBuilder();
    for (StackTraceElement element : e.getStackTrace()) {
        sb.append(element.toString());
        sb.append("\n");
    }
    return sb.toString();
}
jqno
quelle
1
Ich würde mich für eine Erweiterung dieses Ansatzes entscheiden, wenn Sie den Trace kürzen möchten, z. B. einen maxLines-Parameter übergeben und nur so viele Zeilen zum Trace hinzufügen möchten
Rich Seller
Die Klammern nach e.getStackTrace fehlen. public static String stackTraceToString (Ausnahme e) {StringBuilder sb = new StringBuilder (); for (StackTraceElement-Element: e.getStackTrace ()) {sb.append (element.toString ()); sb.append ("<br />"); } return sb.toString (); }
rlc
2
Ich bin mir nicht sicher, aber ich denke, dies wird den Stack-Trace der Root-Cause-Ausnahme nicht drucken.
Apoorv020
7
Was auch immer Sie tun, schneiden Sie die Spur nicht ab. Es ist mir viele, viele Male passiert, dass ich mir eine Stapelspur in den GlassFish-Protokollen angesehen habe, bei der die nützlichen Teile weggeschnitten wurden.
Cayhorstmann
Verwenden Sie String.format("%n")oder etwas Ähnliches, anstatt "\n"DOS-Lamers glücklich zu machen.
Ceving
89

Für mich war der sauberste und einfachste Weg:

import java.util.Arrays;
Arrays.toString(e.getStackTrace());
Vladas Diržys
quelle
37
Der Code ist sauber, die Ausgabe jedoch nicht. Sie müssen am Ende eine .replaceAll (",", "\ n") ausführen. Sie verlieren jedoch den Einzug, den printStackTrace vorschlägt.
Wut
4
Dies ist nützlich, wenn Sie Trace in einer einzigen Zeile
protokollieren
28
public static String getStackTrace(Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    return sw.toString();
}
Akira Yamamoto
quelle
1
Hallo, ich möchte nur darauf hinweisen, dass der Kommentarbereich der zitierten Antwort darauf hinweist, dass die StringWriterund PrintWriterObjekte closed sein sollten .... (oder ich denke, nur die PrintWritermüssen geschlossen werden, da das Schließen auch das schließen sollte StringWriter)
Eric
8
Mit inspiriert meinst du kopiert? Sie setzen es nur in eine Methode ein ... Das Lesen der Antworten hier ist wie das Anschauen von "Groundhog Day"
Murmel
26

Mit dem folgenden Code können Sie die gesamte stackTrace in einem StringFormat abrufen , ohne APIs wie log4J oder sogar zu verwenden 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.
}
Dumonderic
quelle
1
ya aber es ist ein bisschen sperrig, findest du nicht? in jedem Projekt mit angemessener Größe ist die Protokollierung ein Muss, warum also die Mühe machen
mzzzzb
Dieser gibt am Anfang keine Fehlermeldung aus. kann aber hinzugefügt werden
kommradHomer
Möglicherweise möchten Sie einen StringBuffer anstelle einer einfachen Verkettung verwenden.
dedda1994
Dies ist nützlich, wenn Sie die Nachricht aus Datenschutzgründen nicht protokollieren dürfen.
A1m
Beachten Sie
19

Hier ist eine Version, die direkt in Code kopiert werden kann:

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

Oder in einem Fangblock

} catch (Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    logger.info("Current stack trace is:\n" + sw.toString());
}
Rubel
quelle
Dies wird über den Umfang der aktuellen Funktion hinaus fortgesetzt, d. h. wo das Throwabledefiniert ist, richtig?
n611x007
16
Arrays.toString(thrown.getStackTrace())

Ist der einfachste Weg, das Ergebnis in einen String zu konvertieren. Ich verwende dies in meinem Programm, um den Stack-Trace zu drucken

LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});
Ramanan Durairaj
quelle
Hat für mich gearbeitet, nichts sieht beschnitten aus! Einfacher als jede andere Antwort ohne externe Bibliothek, tolle Antwort!
Shaung Cheng
16

Drucken Sie die Stapelverfolgung in a PrintStreamund konvertieren Sie sie dann in a String:

// ...

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

    System.out.println(str);
}
In der Hälfte gebacken
quelle
1
Dies ist die direkteste Antwort
DaSqy Stc
11

Stack-Trace in String drucken

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

Dies ist nützlich, wenn Sie den aktuellen Thread-Stack-Trace drucken möchten, ohne eine Instanz von zu erstellen. ThrowableBeachten Sie jedoch, dass das Erstellen eines neuen Throwableund das Abrufen des Stack-Trace von dort tatsächlich schneller und billiger ist als das Aufrufen Thread.getStackTrace.

Jarek Przygódzki
quelle
11

Kotlin

Wenn Sie die Throwable-Klasse erweitern, erhalten Sie die String-Eigenschaft error.stackTraceString:

val Throwable.stackTraceString: String
  get() {
    val sw = StringWriter()
    val pw = PrintWriter(sw)
    this.printStackTrace(pw)
    return sw.toString()
  }
vonox7
quelle
10
private String getCurrentStackTraceString() {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    return Arrays.stream(stackTrace).map(StackTraceElement::toString)
            .collect(Collectors.joining("\n"));
}
eddyrokr
quelle
1
Vielen Dank, dass Sie eddyrkokr! Es funktioniert perfekt für alle meine Klassen. Ich habe es gerade in der Basis-TestNG-Klasse hinzugefügt und es sammelt nacheinander Stacktraces aus allen Tests!
Krzysztof Walczewski
9

Das clevere Sniping in den ersten Kommentaren war sehr amüsant, aber es hängt wirklich davon ab, was Sie versuchen zu tun. Wenn Sie noch nicht die richtige Bibliothek haben, sind 3 Codezeilen (wie in der Antwort von D. Wroblewski) perfekt. OTOH, wenn Sie bereits über die Bibliothek apache.commons verfügen (wie es die meisten großen Projekte tun), ist Amars Antwort kürzer. OK, es kann zehn Minuten dauern, bis Sie die Bibliothek abgerufen und korrekt installiert haben (weniger als eine, wenn Sie wissen, was Sie tun). Aber die Uhr tickt, so dass Sie möglicherweise nicht die Zeit haben, um zu sparen. Jarek Przygódzki hatte eine interessante Einschränkung - "Wenn Sie keine verschachtelten Ausnahmen benötigen".

Aber was , wenn ich Sie den vollständigen Stack - Traces benötigen, verschachtelt und alle? In diesem Fall besteht das Geheimnis darin, getFullStackTrace von apache.common zu verwenden (siehe http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html) # getFullStackTrace% 28java.lang.Throwable% 29 )

Es hat meinen Speck gerettet. Danke, Amar, für den Hinweis!

Tihamer
quelle
9

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

Der Unterschied zu den anderen Antworten besteht darin, dass es autoFlush auf der verwendet wird PrintWriter.

IvanRF
quelle
8

Ohne das geht java.io.*es so.

String trace = e.toString() + "\n";                     

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

Und dann enthält die traceVariable Ihre Stapelverfolgung. Die Ausgabe enthält auch die ursprüngliche Ursache, die Ausgabe ist identisch mitprintStackTrace()

Beispiel printStackTrace()ergibt:

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)

Die traceZeichenfolge gilt beim Drucken aufstdout

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)
Gala
quelle
5

Scala-Version

def stackTraceToString(e: Exception): String = {
  import java.io.PrintWriter
  val sw = new StringWriter()
  e.printStackTrace(new PrintWriter(sw))
  sw.toString
}
samthebest
quelle
5

Wenn Sie Java 8 verwenden, versuchen Sie dies

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

Den Code für die getStackTrace()Funktion finden Sie Throwable.javaunter:

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

und für StackTraceElementAnbieter toString()wie:

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

Also einfach StackTraceElementmit "\ n" verbinden.

Pengcheng Zhang
quelle
Diese Lösung berücksichtigt nicht den Einzug der Registerkarte "Stapelverfolgung", da sie sonst hervorragend funktioniert!
krizajb
4

eine Erklärung zu Galas Antwort, die auch die Ursachen für die Ausnahme enthält:

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;
}
Ido Flachs
quelle
4

Die Lösung besteht darin, die stackTrace des Arrays in einen String- Datentyp zu konvertieren . Siehe folgendes Beispiel:

import java.util.Arrays;

try{

}catch(Exception ex){
    String stack = Arrays.toString(ex.getStackTrace());
    System.out.println("stack "+ stack);
}
Jorge Santos
quelle
4

Mit der Java 8 Stream API können Sie Folgendes tun:

Stream
    .of(throwable.getStackTrace())
    .map(StackTraceElement::toString)
    .collect(Collectors.joining("\n"));

Es werden Arrays von Stack-Trace-Elementen verwendet, in Zeichenfolgen konvertiert und zu mehrzeiligen Zeichenfolgen zusammengefügt.

ivanjermakov
quelle
2
Diese Lösung entfernt Nachricht und ignoriert alle übergeordneten Spuren
Judovana
3

Mein Oneliner zum Konvertieren der Stapelverfolgung in die beiliegende mehrzeilige Zeichenfolge:

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

Einfach an den Logger "wie es ist" zu übergeben.

Andrey Lebedenko
quelle
Sie erhalten etwas, das sich von printStackTrace()hier unterscheidet. Sie verlieren: 1) Ausnahme, die geworfen wurde; 2) Ursachen und ihre
Stapelverfolgung
Der Unterschied ist durchaus zu erwarten, da die Konvertierung des printStackTrace()Nie ein Teil der Frage war.
Andrey Lebedenko
2

Wenn Sie keine externe Bibliothek verwenden möchten und nicht für Android entwickeln , können Sie eine Erweiterungsmethode wie die folgende erstellen :

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();
}
Kapé
quelle
2

Alte Frage, aber ich möchte nur den Sonderfall hinzufügen, in dem Sie nicht den gesamten Stapel drucken möchten , indem Sie einige Teile entfernen, an denen Sie eigentlich nicht interessiert sind, mit Ausnahme bestimmter Klassen oder Pakete.

Anstelle einer PrintWriterVerwendung 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);

Wo die SelectivePrintWriterKlasse gegeben ist durch:

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

Bitte beachten Sie, dass diese Klasse leicht angepasst werden kann, um nach Regex containsoder anderen Kriterien herauszufiltern . Beachten Sie auch, dass dies von den ThrowableImplementierungsdetails abhängt (wahrscheinlich nicht geändert, aber immer noch).

MarcG
quelle
1
Ja, das funktioniert gut und ist eigentlich eine ziemlich nützliche Idee.
Gil.fernandes
2
 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);
        }
    }
}

Wenn Sie das Programm ausführen, ist die Ausgabe ähnlich:

java.lang.ArithmeticException: / by zero
at PrintStackTrace.main(PrintStackTrace.java:9)
Prakhar Nigam
quelle
1

Ich frage mich, warum niemand erwähnt hat ExceptionUtils.getStackFrames(exception)

Für mich ist es der bequemste Weg, Stacktrace mit all seinen Ursachen bis zum Ende zu sichern:

String.join("\n", ExceptionUtils.getStackFrames(exception));
Andrey Sarul
quelle
0

Warnung: Dies mag ein bisschen vom Thema abweichen, aber na ja ...;)

Ich weiß nicht, warum der ursprüngliche Postergrund dafür war, dass der Stack-Trace überhaupt als Zeichenfolge verwendet werden sollte. Wenn der Stack-Trace in einem SLF4J / Logback-LOG enden sollte, aber keine Ausnahme ausgelöst wurde oder werden sollte, gehe ich folgendermaßen vor:

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
}

Ich mag es, weil es keine externe Bibliothek erfordert (außer Ihrem Protokollierungs-Backend, das natürlich sowieso die meiste Zeit vorhanden sein wird).

Alexander Wessel
quelle