7

We are making an Excel-like system. When we open a document and found unsupported functions we threw exception. We just support small subset of excel functions, this could happen frequently. The problem is when there are a lot of cells that contains unsupported functions, lots and lots of exception instances are created. And creating those many exception instances consumes unignorable amount of time.

We don't have any special properties within the exception class. What we need to know is the fact that the exception is thrown. We just found that the error has occurred and mark the cell as error.

So we decided to share one exception instance and throw it whenever needed. The exception instance can be thrown by multiple threads. I suspect that the stack trace could be corrupted, however, we don't see it. We just catch the exception, and mark the corresponding cell as error.

My question is: In this situation, is it safe to share exception instance? Well, I read the following article: Java: is Exception class thread-safe? But the context seems to be different.

Thank you for reading this long question and response in advance.

Community
  • 1
  • 1
ntalbs
  • 28,700
  • 8
  • 66
  • 83

2 Answers2

6

[...] is it safe to share exception instance?

Yes, if you're careful.

If you're not careful, the getStackTrace for instance may get messed up. Either make sure each thread has it's own exception object, or override getStackTrace and return an empty array.

(The JVM actually reuses exception instances in some cases. If it runs out of memory, it will reuse a preallocated OutOfMemoryError instead of trying to create a new one for instance. In this case the getStackTrace returns an empty array.)

Related question:

Community
  • 1
  • 1
aioobe
  • 413,195
  • 112
  • 811
  • 826
5

I suspect that the stack trace could be corrupted.

It won't get corrupted.

However, since the stack trace is captured when the exception instance is created, if you reuse the exception the stack trace won't be correct. Similarly, there's no API method to change the exception's message string after creation, so a "shared" exception will always have the same message.


This has the "smell" of a premature optimization and/or using an exception in a "non-exceptional" control flow. The best approach would be to simply create a new exception instance each time you throw, and only mess around with exception sharing if you have a definite (real) performance issue.

UPDATE - apparently this is NOT a premature optimization. However, the fact that your profiling shows that you are spending a significant amount of time in creating exception instances, I would recommend that you at least consider alternative optimizations that involve reducing the frequency of throwing exceptions.


Well, I have to override the getStackTrace() to return an empty array.

No. A better idea is to override the fillInStackTrace() method to not capture one. There is also a clean way to do this in Java 7 using the Exception constructor arguments.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thank you for the detailed explanation. Actually we profiled the application with visualvm and found that lots of time consumed by creating exception instances. We hope to use Java 7, however, we can't use it for some reason. Anyway, Thank you very much. I'd better override fillInStackTrace() method in my exception class. – ntalbs Jul 13 '12 at 15:46