我将首先用我的用例快速激发问题。 我的库需要将Java异常分类器暴露给它插入的框架。例如:
enum Classification { FATAL, TRANSIENT, UNKNOWN }
Classification classify(Throwable t) {
if (t instanceof MyTransientException)
return Classification.TRANSIENT;
else if (t instanceof MyFatalException)
return Classification.FATAL;
else
return Classification.UNKNOWN;
}
有时,由于我无法控制的原因,传递的异常是我感兴趣的一个包装器所以我想搜索它的原因链。我最初的想法是:
Classification classify(Throwable t) {
if (t == null)
return Classification.UNKNOWN;
if (t instanceof MyTransientException)
return Classification.TRANSIENT;
else if (t instanceof MyFatalException)
return Classification.FATAL;
else
return classify(t.getCause());
}
不幸的是,如果传递的异常在其因果链中有一个循环,这可能导致无限递归。这样的异常很可能不会被传递,并且如果创建了这样的异常,可能会在系统的其他地方出现错误,但我对我的库负责生产的可能性感到非常不舒服。如果发生中断。 Throwable的API和javadoc没有明确禁止这种可能性,因为循环在因果链中本质上是无意义的。
我注意到Guava有一个@Beta方法来提取因果链, Throwables.getCausalChain,但它的实现很容易受到同样的问题 - 最终会抛出一个OOME。
我打算用一个 身份哈希集 检测周期并降低风险,但我想听听别人如何看待这个问题。你觉得我过度防守吗?你会怎么做?