gpt4 book ai didi

java - 跨线程保留 Java 堆栈跟踪

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:39:57 25 4
gpt4 key购买 nike

我正在使用ExecutorService异步发送邮件,所以有一个类:

class Mailer implements Runnable { ...

处理发送。记录任何被捕获的异常,例如(匿名):

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]

不是很有帮助 - 我需要查看调用导致所有这些的 ExecutorService 的堆栈跟踪。我的解决方案是创建一个空的 Exception 并将其传递给 Mailer:

executorService.submit(new Mailer(foo, bar, new Exception()));
...
// constructor
public Mailer(foo, bar, Exception cause) { this.cause = cause; ...

现在在异常的情况下,我想记录问题本身及其来自其他线程的原因:

try {
// send the mail...
} catch (Throwable t) {
LOG.error("Stuff went wrong", t);
LOG.error("This guy invoked us", cause);
}

这很好但会产生两个日志。我想将 tcause 组合成一个异常并记录那个异常。在我看来,t 导致了cause,所以使用cause.initCause(t) 应该是正确的方法。并且有效。我看到了完整的堆栈跟踪:从发起调用的地方一直到 AddressException

问题是,initCause() 只工作一次然后就崩溃了。 问题 1: 我可以克隆 Exception 吗?我会克隆 cause 并每次用 t 初始化它。

我尝试了 t.initCause(cause),但它立即崩溃了。

问题 2:是否有另一种巧妙的方法来组合这 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 );
}
}

现在在你的 catch 子句中你可以这样做:

catch ( Throwable cause ) {
LOG( "This happened", new CrossThreadException( cause, originalStackTrace ) );
}

这将为您提供两个堆栈跟踪之间的边界。

关于java - 跨线程保留 Java 堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30708731/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com