Throwable.printStackTrace()
schreibt den Stack-Trace in System.err
PrintStream. Der System.err
Stream und der zugrunde liegende Standardausgabestream "Fehler" des JVM-Prozesses können von umgeleitet werden
- Aufrufen,
System.setErr()
wodurch das Ziel geändert wird, auf das verwiesen wird System.err
.
- oder durch Umleiten des Fehlerausgabestreams des Prozesses. Der Fehlerausgabestream wird möglicherweise in eine Datei / ein Gerät umgeleitet
- deren Inhalt vom Personal ignoriert werden kann,
- Die Datei / das Gerät kann möglicherweise nicht protokolliert werden, was darauf schließen lässt, dass ein Prozessneustart erforderlich ist, um das geöffnete Datei- / Gerätehandle zu schließen, bevor der vorhandene Inhalt der Datei / des Geräts archiviert wird.
- oder die Datei / das Gerät verwirft tatsächlich alle darauf geschriebenen Daten, wie dies der Fall ist
/dev/null
.
Daraus folgt, dass das Aufrufen nur Throwable.printStackTrace()
ein gültiges (nicht gutes / gutes) Verhalten bei der Ausnahmebehandlung darstellt
- Wenn Sie
System.err
während der gesamten Lebensdauer der Anwendung nicht neu zugewiesen wurden,
- und wenn Sie keine Protokollrotation benötigen, während die Anwendung ausgeführt wird,
- und wenn akzeptiert / entworfen, besteht die Protokollierungspraxis der Anwendung darin, in
System.err
(und den Standardfehlerausgabestream der JVM) zu schreiben .
In den meisten Fällen sind die oben genannten Bedingungen nicht erfüllt. Man kennt möglicherweise keinen anderen Code, der in der JVM ausgeführt wird, und man kann die Größe der Protokolldatei oder die Laufzeit des Prozesses nicht vorhersagen, und eine gut konzipierte Protokollierungspraxis würde sich darauf konzentrieren, "maschinenparsierbare" Protokolldateien zu schreiben (a bevorzugte, aber optionale Funktion in einem Logger) an einem bekannten Ziel, um die Unterstützung zu unterstützen.
Schließlich sollte man bedenken, dass die Ausgabe von Throwable.printStackTrace()
definitiv mit anderen Inhalten verschachtelt wird, auf die geschrieben wurde System.err
(und möglicherweise sogar, System.out
wenn beide auf dieselbe Datei / dasselbe Gerät umgeleitet werden). Dies ist ein Ärger (für Single-Threaded-Apps), mit dem man sich befassen muss, da die Daten um Ausnahmen in einem solchen Fall nicht leicht zu analysieren sind. Schlimmer noch, es ist sehr wahrscheinlich, dass eine Multithread-Anwendung sehr verwirrende Protokolle erstellt, da sie Throwable.printStackTrace()
nicht threadsicher ist .
Es gibt keinen Synchronisationsmechanismus, mit dem das Schreiben des Stack-Trace synchronisiert werden kann, System.err
wenn mehrere Threads gleichzeitig aufgerufen Throwable.printStackTrace()
werden. Um dies zu beheben, muss Ihr Code auf dem zugehörigen Monitor synchronisiert werden System.err
(und auch System.out
, wenn die Zieldatei / das Gerät identisch ist), und das ist ein ziemlich hoher Preis für die Vernunft von Protokolldateien. Um ein Beispiel zu nehmen, die ConsoleHandler
und StreamHandler
sind Klassen , die für das Anhängen Protokollaufzeichnungen in Konsole, in der Logging - Einrichtung zur Verfügung gestellt von java.util.logging
; Der eigentliche Vorgang zum Veröffentlichen von Protokolldatensätzen wird synchronisiert. Jeder Thread, der versucht, einen Protokolldatensatz zu veröffentlichen, muss auch die Sperre für den mit dem verknüpften Monitor erhaltenStreamHandler
Beispiel. Wenn Sie die gleiche Garantie für nicht verschachtelte Protokolldatensätze mit System.out
/ haben möchten, müssen System.err
Sie dies auch sicherstellen - die Nachrichten werden auf serialisierbare Weise in diesen Streams veröffentlicht.
In Anbetracht all dieser Punkte und der sehr eingeschränkten Szenarien, in denen dies Throwable.printStackTrace()
tatsächlich nützlich ist, stellt sich häufig heraus, dass das Aufrufen eine schlechte Praxis ist.
Wenn Sie das Argument in einem der vorherigen Absätze erweitern, ist es auch eine schlechte Wahl, es Throwable.printStackTrace
in Verbindung mit einem Logger zu verwenden, der auf die Konsole schreibt. Dies liegt zum Teil daran, dass der Logger auf einem anderen Monitor synchronisiert wird, während Ihre Anwendung (möglicherweise, wenn Sie keine verschachtelten Protokolldatensätze wünschen) auf einem anderen Monitor synchronisiert wird. Das Argument gilt auch, wenn Sie in Ihrer Anwendung zwei verschiedene Logger verwenden, die auf dasselbe Ziel schreiben.