Java 链式异常中的循环

Java 链式异常中的循环,java,guava,Java,Guava,我将首先用我的用例快速地激发这个问题。 我的库需要将Java异常分类器公开给它所插入的框架。例如: enum Classification { FATAL, TRANSIENT, UNKNOWN } Classification classify(Throwable t) { if (t instanceof MyTransientException) return Classification.TRANSIENT; else if (t instanceof

我将首先用我的用例快速地激发这个问题。 我的库需要将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方法来提取因果链,但是它的实现容易受到相同问题的影响——它最终会抛出一个OOME


我计划使用一种新的方法来检测周期并降低风险,但我想听听其他人如何看待这个问题。你认为我是不是过于保守了?你会怎么做?

你这么认真真是太好了。但你不想涉足凯夫拉尔靴子的制造业


如果一个用户做了一些事情,使得甚至
都可以扔掉。printStackTrace
进入无限递归,那么这个用户就无能为力了。甚至不用担心这一点。

我认为在您自己的代码中这样做是出于防御性的考虑,但是因为现在我们使用了许多库,您永远不知道哪一个库实际上会做一些出乎意料的事情,比如创建一个causechain循环

Apache Commons在它的
例外部分中处理这个问题。比如在中国。它以一种相当简单的方式实现这一点:

public static List<Throwable> getThrowableList(Throwable throwable) {
    final List<Throwable> list = new ArrayList<>();
    while (throwable != null && !list.contains(throwable)) {
        list.add(throwable);
        throwable = throwable.getCause();
    }
    return list;
}
public静态列表getThrowableList(Throwable-Throwable){
最终列表=新的ArrayList();
while(throwable!=null&&!list.contains(throwable)){
列表。添加(可丢弃);
throwable=throwable.getCause();
}
退货清单;
}
通过使用帮助器库而不是构建自己的帮助器库,您可以防止在您从未想到自己的事情上出现错误