如何记录由finally块';Java中的异常?

如何记录由finally块';Java中的异常?,java,debugging,exception,finally,Java,Debugging,Exception,Finally,请注意: 我知道在Java中,finally块不应该抛出异常,否则这是[非常非常]糟糕的做法 我知道我应该使用try catchinsidefinally来处理(例如记录或忽略)所有异常并防止它们传播 我知道Java7的Throwable有getsuppreserved方法,但我的目标是Java5和Java6 问题:在Java中,在try finally中,如果try块引发了异常(将其命名为A),则控件会到达finally块(在没有异常的情况下,它也会到达,但在这个问题中并不有趣)。然后,如果f

请注意: 我知道在Java
中,finally
块不应该抛出异常,否则这是[非常非常]糟糕的做法
知道我应该使用
try catch
inside
finally
来处理(例如记录或忽略)所有异常并防止它们传播
知道Java7的Throwable有
getsuppreserved
方法,但我的目标是Java5和Java6

问题:在Java中,在
try finally
中,如果
try
块引发了异常(将其命名为A),则控件会到达
finally
块(在没有异常的情况下,它也会到达,但在这个问题中并不有趣)。然后,如果
finally
块抛出一个异常(将其命名为B),则异常A被抑制,或者被屏蔽/吞没,异常B被传播到调用方

问题:当一个异常被另一个异常抑制并记录第一个异常时,我是否可以检测到这种情况
... 我花了太多的时间来推理为什么会抛出特定的异常,而不知道到底发生了什么

理由:经常出现问题的
try finally
块在库中编码(今天是Hibernate),因此我无法修改它们

解决方案约束:正如我在开始时所指出的,可能的解决方案不应该依赖于Java7,但另一方面,不需要是生产级的(这样做会有好处)。AOP是这里的一个选项


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

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

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

例如:

try {
    ...
} catch (Exception e) {
    log.boom("Ouchies happened here", e);
}
并不是每个异常都会重新抛出

然而,在某个级别上,大多数异常最终都会被抛出,以便调用方能够处理它们

因此,考虑到您很可能会“泄漏”异常,游戏就是尝试找到“泄漏”异常

使用AOP,您可以在创建每个异常时将其删除(无论您是可以在异常级别执行此操作,还是必须在单个类级别执行此操作,我不能说——在本例中,您对AOP的实际操作并不太熟悉)

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

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

理想情况下,经过一点分析后,您将能够确定哪些块不是简单地抛出的(而是以其他方式处理的),哪些块实际上被您的finally块遮挡


它是不完美的,而且最肯定的是我不会在生产中使用它(坦白地说,我只需要在录音之类的所有竞争条件下投入大量的工作,比我想为这种调试做的工作还要多)。但它可能会提供您所需的信息,尤其是在一个小类域中使用时。

我无法最终修改
。它们被密封在jar文件中。有很多方法:)如果我截获每一个方法,这会使JVM运行缓慢吗?我注意到,有时候Eclipse的断点会将JVM的速度降低50倍(JVM1.6,相当不错的Eclipse版本)……显然,拦截会带来一些成本,但它不应该破坏系统。但这是另一个节约使用它的原因,而且只用于调试。您不必在每个方法上都使用它,只需在每个要跟踪异常的入口点上使用它即可。