7

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

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

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

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

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

4

2 回答 2

6

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

是的,如果你小心的话。

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

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

相关问题:

于 2012-07-13T15:15:14.213 回答
5

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

它不会被破坏。

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


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

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


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

不,一个更好的主意是重写该fillInStackTrace()方法以不捕获一个。Exception在 Java 7 中还有一种使用构造函数参数的简洁方法可以做到这一点。

于 2012-07-13T15:34:22.740 回答