【问题标题】:Is it safe to share exception instance共享异常实例是否安全
【发布时间】:2012-07-13 15:12:06
【问题描述】:

我们正在制作一个类似 Excel 的系统。当我们打开一个文档并发现不受支持的功能时,我们会抛出异常。我们只支持一小部分 excel 函数,这可能经常发生。问题是当有很多包含不受支持的功能的单元格时,会创建大量异常实例。并且创建这么多异常实例会消耗不可忽视的时间。

我们在异常类中没有任何特殊属性。我们需要知道的是抛出异常的事实。我们刚刚发现发生了错误,并将单元格标记为错误。

所以我们决定共享一个异常实例并在需要时抛出它。异常实例可以由多个线程抛出。我怀疑堆栈跟踪可能已损坏,但是,我们没有看到它。我们只是捕获异常,并将相应的单元格标记为错误。

我的问题是: 在这种情况下,共享异常实例是否安全? 好吧,我阅读了以下文章: Java: is Exception class thread-safe? 但上下文似乎有所不同。

感谢您提前阅读这么长的问题和回复。

【问题讨论】:

    标签: java exception exception-handling


    【解决方案1】:

    [...] 共享异常实例是否安全?

    是的,如果你小心的话。

    如果您不小心,例如 getStackTrace 可能会搞砸。要么确保每个线程都有自己的异常对象,要么覆盖getStackTrace 并返回一个空数组。

    (在某些情况下,JVM实际上会重用异常实例。如果内存不足,它将重用一个预先分配的OutOfMemoryError,而不是尝试创建一个新实例。在这种情况下,getStackTrace返回一个空数组。)

    相关问题:

    【讨论】:

    • 谢谢。好吧,我必须重写 getStackTrace() 以返回一个空数组。
    【解决方案2】:

    我怀疑堆栈跟踪可能已损坏。

    它不会被损坏。

    但是,由于堆栈跟踪是在创建异常实例时捕获的,如果您重用异常,堆栈跟踪将不正确。同样,没有 API 方法可以在创建后更改异常的消息字符串,因此“共享”异常将始终具有相同的消息。


    这有过早优化和/或在“非异常”控制流中使用异常的“气味”。最好的方法是每次throw 时简单地创建一个新的异常实例,并且只有在遇到明确的(真正的)性能问题时才使用异常共享。

    更新 - 显然这不是过早的优化。然而,您的分析表明您在创建异常实例方面花费了大量时间,我建议您至少考虑替代优化,包括降低抛出异常的频率。 p>


    好吧,我必须重写 getStackTrace() 以返回一个空数组。

    没有。一个更好的主意是覆盖fillInStackTrace() 方法以不捕获一个。在 Java 7 中也有一种简洁的方法可以使用 Exception 构造函数参数来执行此操作。

    【讨论】:

    • 感谢您的详细解释。实际上,我们使用 visualvm 分析了应用程序,发现创建异常实例消耗了大量时间。我们希望使用 Java 7,但是由于某种原因我们不能使用它。无论如何,非常感谢。我最好在我的异常类中重写 fillInStackTrace() 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-14
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多