Java-Stack-Trace über Threads hinweg beibehalten

8

Ich verwende ExecutorService , um Mails asynchron zu versenden, also gibt es eine Klasse:

%Vor%

Das erledigt das Senden. Jede Ausnahme, die abgefangen wird, wird protokolliert, für (anonymisiertes) Beispiel:

%Vor%

Nicht sehr hilfreich - Ich muss den Stack-Trace sehen, der die ExecutorService aufgerufen hat, die das alles verursacht hat. Meine Lösung besteht darin, ein leeres Exception zu erstellen und es in Mailer :

zu übergeben %Vor%

Und jetzt im Ausnahmefall möchte ich das Problem selbst und seine Ursache von dem anderen Thread protokollieren:

%Vor%

Das funktioniert großartig, produziert aber zwei Protokolle. Ich möchte t und cause zu einer einzigen Ausnahme kombinieren und diese protokollieren. Meiner Meinung nach verursacht t cause , also sollte cause.initCause(t) der richtige Weg sein. Und funktioniert. Ich sehe einen vollständigen Stack-Trace: von wo der Aufruf den ganzen Weg bis zum AddressException herrührt.

Problem ist, initCause() funktioniert nur einmal und stürzt dann ab. Frage 1: kann ich Exception klonen? Ich würde cause klonen und es jedes Mal mit t initiieren.

Ich habe versucht, t.initCause(cause) , aber das stürzt sofort ab.

Frage 2: Gibt es eine andere clevere Möglichkeit, diese beiden Ausnahmen zu kombinieren? Oder behalte nur einen Thread-Kontext im anderen Thread-Kontext für Protokollierungszwecke?

    
vektor 08.06.2015, 12:06
quelle

4 Antworten

9

Nach meinem Kommentar, das ist tatsächlich, was ich im Sinn hatte. Wohlgemerkt, ich kann es im Moment nicht testen.

Was Sie von Ihrem übergeordneten Thread übergeben, ist New Exception().getStackTrace() . Oder noch besser, wie @Radiodef kommentierte, Thread.currentThread().getStackTrace() . Es ist also im Grunde ein StackTraceElement[] -Array.

Nun können Sie etwas wie:

haben %Vor%

Nun können Sie in Ihrer catch-Klausel etwas wie:

tun %Vor%

Damit erhalten Sie eine Grenze zwischen den beiden Stack-Traces.

    
RealSkeptic 08.06.2015, 12:35
quelle
3

Sie können das Objekt Future<v> verwenden, das von Ihrem Submit-Aufruf zurückgegeben wurde, und anschließend die Methode get() aufrufen. Wenn während der Ausführung der Task eine Ausnahme aufgetreten ist, wird sie erneut ausgelöst.

Eine weitere Option besteht darin, den standardmäßigen Ausnahmebehandler für die Thread-Factory anzupassen, der die Threads für Ihr ExecutorService erstellt. Weitere Informationen finden Sie unter Thread.UncaughtExceptionHandler

    
Maxim Kirilov 08.06.2015 12:29
quelle
0

Was ich tue, ist, dass der Thread, den du aufruft, die Ausnahme speichert, anstatt sie zu werfen.

Dann kann der Haupt-Thread, der ihn gestartet hat, ihn abfragen, um festzustellen, ob eine Ausnahme aufgetreten ist. Wenn einer hat, dann kann er die Ausnahme bekommen und einen als Ursache dafür ausgeben.

Ich glaube nicht, dass Sie eine Ausnahme klonen können.

Als eine allgemeine Regel ist diese Art des Bastelns mit Ausnahmen schlechte Nachrichten und ein Zeichen, dass es einige Probleme mit dem allgemeinen Ansatz zur Fehlerbehandlung im Code geben kann.

Es ist schwer zu tun, weil Sie nicht wirklich dazu bestimmt sind.

    
Phil Anderson 08.06.2015 12:17
quelle
0

Sie können die Klasse ListableFuture aus der Google Guava-Bibliothek verwenden. Siehe Ссылка

%Vor%     
Wim Deblauwe 08.06.2015 12:31
quelle