2011-03-30 42 views
4

刚一说明: 我知道在Java中finally块不应该抛出异常,否则就[非常,非常,非常]糟糕的做法。
知道,我应该在finally内使用try-catch来处理(例如记录或忽略)所有异常并防止它们传播。
知道该爪哇7的Throwable的具有getSuppressed的方法,但我定位的Java 5 & 6.如何记录Java中finally块的异常所掩盖的异常?

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

问:我可以以某种方式检测时,唯一的例外是另一个抑制情况和日志/记录的第一个?
......我花了太多时间推理为什么特定的异常已经抛出,不知道什么真的发生了。

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

解决方案的限制:正如我在开始时指出,可能的解决方案不应该转发关于Java 7,但是,在另一方面,也不需要是生产高档(是这样的,将是一个奖金)。 AOP是这里的一个选项。

(请不要张贴琐碎的答案,如“使用Java 7的开发” :)

回答

1

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

例如:

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

并不是每一个异常被重新抛出。

然而,在一定的水平MOST例外情况是,最终抛出,使主叫方可以处理他们。

因此,鉴于您可能会“泄漏”异常,游戏将尝试找到“泄漏”的例外。

使用AOP可以让每个异常在创建时消失(无论您是在异常级别执行此操作,还是必须在单个类级别执行此操作,我都不能说 - 不熟悉AOP在这种情况下在实践中)。

一旦你捕捉异常,因为它们被创建,然后你开始通过AOP包装方法调用。当你这样做时,你可以捕获方法抛出的异常。

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

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

这是不完美的,当然我不会在生产中使用它(我只需要在录制东西等所有竞争条件方面投入很多工作。坦率地说,这样做的调试)。但是它可能会给你提供你正在寻找的信息,特别是当在一小部分课程中谨慎使用时。

+0

如果我拦截每个方法,这会使JVM运行缓慢吗?我注意到,有时候Eclipse的断点将JVM放慢了50倍(JVM 1.6,体面的Eclipse版本)...... – 2011-03-31 07:39:57

+0

很显然,拦截将会产生一些成本,但它不应该削弱系统。但另一个原因是要谨慎使用它,只能用于调试。您不必在每种方法上都有它,只需要每个您想要追踪异常的入口点。 – 2011-03-31 15:53:20

0

有一个名为“ExceptionCheck()”一个JNI方法,该方法,这并不奇怪,对于一个挂起的异常检查。你可以把它在一个本地方法的中间,看一些现有的呼叫已抛出其正在等待周围的JNI方法返回之前,它实际上抛出的异常。我不知道你是否可以从最后调用本地方法,然后尝试使用ExceptionCheck来查看是​​否有未决的异常,如果可以的话。我不知道它是否会,但我会说这是值得一试的。

+0

我无法修改'finally'。他们被密封在jar文件中。并且有很多:) – 2011-03-30 21:55:06