4

请注意:我知道在 Javafinally块中永远不应该抛出异常,否则这是 [非常、非常、非常] 不好的做法。
知道我应该使用try-catchinsidefinally来处理(例如记录或忽略)所有异常并防止它们传播。
知道Java 7 的 Throwable 有getSuppressed方法,但我的目标是 Java 5 和 6。

问题:在Java中,try-finally如果块抛出异常(命名为Atry,则控制到达finally块(如果没有异常,它也会到达它,但在这个问题中并不有趣)。然后,如果finallyblock 抛出异常(将其命名为B),异常A被抑制或屏蔽/吞咽,异常B被传播给调用者。

问题:当一个异常被另一个异常抑制并记录/记录第一个异常时,我能以某种方式检测到这种情况吗?
...我花了太多时间来推理为什么会抛出特定的异常并且不知道到底发生了什么。

理由:经常有问题try-finally的块被编码在一个库中(今天它是 Hibernate),所以我无法修改它们。

解决方案限制:正如我在开头所指出的,可能的解决方案不应该依赖于 Java 7,但另一方面,不需要是生产级的(如果是这样将是一个奖励)。AOP 是这里的一个选项。

(请不要发布诸如“使用 Java 7 进行开发”之类的琐碎答案:)

4

2 回答 2

1

我认为的问题是,即使使用 AOP 也无法拦截异常消费过程。使用 AOP,您可以捕获所有创建的异常,但您无法知道它们何时被消耗。

例如:

try {
    ...
} catch (Exception e) {
    log.boom("Ouchies happened here", e);
}

并非每个异常都会重新抛出。

但是,在某个级别上,最终会抛出大多数异常,以便调用者可以处理它们。

因此,考虑到无论如何您都可能“泄漏”异常,游戏将尝试找到“泄漏”异常。

使用 AOP,您可以在创建每个异常时将其消除(您是否可以在异常级别执行此操作,或者必须在单个类级别执行此操作,我不能说 - 在实践中对 A​​OP 不太熟悉案子)。

一旦您在创建异常时捕获它们,您就开始通过 AOP 包装方法调用。执行此操作时,您可以捕获该方法引发的异常。

因此,通过一点工作,您就知道从方法返回时 a) 创建了哪些异常,b) 抛出了哪些异常。如果您从方法中遍历返回的异常的“由”树的异常,则可以将它们从“此方法创建的异常”列表中抛出。其余的是泄漏。

理想情况下,经过一些分析,您将能够确定哪些根本没有被抛出(但以其他方式处理),哪些实际上被您的 finally 块遮住了。

它是不完美的,而且我肯定不会在生产中使用它(我只需要在围绕录制内容等的所有竞争条件下投入大量工作。比我想做的更多工作坦率地说,调试)。但它可能会为您提供您正在寻找的信息,尤其是在少量类域中谨慎使用时。

于 2011-03-30T21:51:43.943 回答
0

有一个名为“ExceptionCheck()”的 JNI 方法,毫不奇怪,它会检查挂起的异常。您可以在本机方法的中间调用它,以查看某个先前的调用是否引发了异常,该异常正在等待 JNI 方法在实际引发之前返回。我想知道您是否可以从 finally 调用本机方法,然后尝试使用 ExceptionCheck 来查看是否有待处理的异常,如果可以的话。我不知道它是否会,但我会说它值得一试。

于 2011-03-30T21:51:24.930 回答