vek*_*tor 9 java logging multithreading stack-trace
我ExecutorService用来异步发送邮件,所以有一个类:
class Mailer implements Runnable { ...
Run Code Online (Sandbox Code Playgroud)
处理发送.对于(匿名)示例,将记录捕获的任何异常:
javax.mail.internet.AddressException: foo is bar
at javax.mail.internet.InternetAddress.checkAddress(InternetAddress.java:1213) ~[mail.jar:1.4.5]
at javax.mail.internet.InternetAddress.parse(InternetAddress.java:1091) ~[mail.jar:1.4.5]
at javax.mail.internet.InternetAddress.parse(InternetAddress.java:633) ~[mail.jar:1.4.5]
at javax.mail.internet.InternetAddress.parse(InternetAddress.java:610) ~[mail.jar:1.4.5]
at mycompany.Mailer.sendMail(Mailer.java:107) [Mailer.class:?]
at mycompany.Mailer.run(Mailer.java:88) [Mailer.class:?]
... suppressed 5 lines
at java.lang.Thread.run(Thread.java:680) [?:1.6.0_35]
Run Code Online (Sandbox Code Playgroud)
不是很有帮助 - 我需要看到调用ExecutorService导致所有这一切的堆栈跟踪.我的解决方案是创建一个空Exception并将其传递给Mailer:
executorService.submit(new Mailer(foo, bar, new Exception()));
...
// constructor
public Mailer(foo, bar, Exception cause) { this.cause = cause; ...
Run Code Online (Sandbox Code Playgroud)
现在在异常的情况下,我想从另一个线程记录问题本身及其原因:
try {
// send the mail...
} catch (Throwable t) {
LOG.error("Stuff went wrong", t);
LOG.error("This guy invoked us", cause);
}
Run Code Online (Sandbox Code Playgroud)
这很好但产生了两个日志.我想结合t,并cause进入一个异常和日志之一.在我看来,t造成的cause,所以使用cause.initCause(t)应该是正确的方式.并且工作.我看到了一个完整的堆栈跟踪:从呼叫始终一直到AddressException.
问题是,initCause()只能工作一次然后崩溃.问题1:我可以克隆Exception吗?我每次都克隆cause并初始化它t.
我试过了t.initCause(cause),但是马上就崩溃了.
问题2:是否有另一种智能方法来组合这两个例外?或者只是在另一个线程上下文中保留一个线程上下文用于记录目的?
根据我的评论,这实际上是我的想法.请注意,我目前没有办法测试它.
你从父线程传递的是New Exception().getStackTrace().或者更好,正如@Radiodef评论的那样Thread.currentThread().getStackTrace().所以它基本上是一个StackTraceElement[]数组.
现在,您可以拥有以下内容:
public class CrossThreadException extends Exception {
public CrossThreadException( Throwable cause, StackTraceElement[] originalStackTrace ) {
// No message, given cause, no supression, stack trace writable
super( null, cause, false, true );
setStackTrace( originalStackTrace );
}
}
Run Code Online (Sandbox Code Playgroud)
现在在您的catch子句中,您可以执行以下操作:
catch ( Throwable cause ) {
LOG( "This happened", new CrossThreadException( cause, originalStackTrace ) );
}
Run Code Online (Sandbox Code Playgroud)
这将为您提供两个堆栈跟踪之间的边界.