views:

586

answers:

4

A collegue of mine at work gave a presentation on static factory methods (right out of Effective Java), and then gave an example of its use for obtaining static / singleton exceptions.

This set off a red flag for me. Aren't exceptions stateful? Aren't they populated by the JVM for stack trace info? What savings do you really get with this, since exceptions should only occur for, well, exceptional situations?

My knowledge on Exceptions is rather limited, so I come to you with this: will singleton exceptions work, and is there any reason to use them?

+1  A: 

I can imagine a situation where you want to be able to detect in your exception conditions whether or not an exception has already been thrown by another part of your application; I can see using a singleton exception for that sort of purpose; but it seems sort of redundant. Essentially, it's conflating the idea of a semaphore ("something happened") with an Exception ("something happened to ME").

McWafflestix
+14  A: 

Singleton exceptions are supposed to be a performance optimization. The thinking is that you eliminate the cost of populating the stack trace when creating an exception which is usually the most expensive part of exceptions.

If the exception were sufficiently unique and descriptive and the stacktrace was not going to be used, then a singleton could potentially be effective. You could design the app such that a specific exception type with a specific message always means that an exception orgininated from a specific location. Then the stack trace would be irrelevant.

The April 22, 2003 Tech Tips article describes a scenario where you reuse an exception. In this case, they are trying to game the garbage collector by reducing the number of objects created. If you skipped the populateStackTrace() call, you would not have to worry about threading.

Generally, if the performance impact of an exception is causing problems, that is a sign that exceptions are being used for application logic and an error-code should be used instead.

In newer JVM's (1.4+, I believe), this "optimization" can be done automatically by the JVM when running in "-server" mode. This hotspot optimization can be controlled by the option -XX:+OmitStackTraceInFastThrow.

Personally, I would recommend against using the singleton exception [anti-]pattern.

James Schek
Interesting answer. I agree with your third paragraph most strongly; exceptions should be exceptional and if they're firing frequently enough to cause a performance problem, you've got to rethink your code.
Randolpho
Very interesting answer.
McWafflestix
The JVM will actually start throwing singleton RuntimeExceptions (e.g. NPE) if one is thrown from the same location several times, controlled by the `-XX:[+-]OmitStackTraceInFastThrow` JVM option. So if someone sends you a log with an NPE and no backtrace, that might be why :)
araqnid
+3  A: 

Although I heartily disagree with the approach, Singleton Exceptions can work in a single-threaded environment.

Folks who suggest Singleton Exception patterns tend to be used to the old c-style invoke/error/check-error paradigm, and want to translate that in one of those new-fangled "Object Orientated" languages.

It's possible, but I call it code smell.

Randolpho
Singleton Exceptions work fine in a multithreaded environment. The exception is only modified when you invoke fillInStackTrace(). If you use the stack as-is, you can throw a single exception object from as many threads as you can muster.
James Schek
Also--*strongly* agree with C-style comment.
James Schek
Java is never a single-threaded environment.
Tom Hawtin - tackline
A: 

If a "static factory method" keeps returning the same object, it isn't really a factory method.

Even java.lang.Throwable has two items of mutable state: the stack trace and the initial cause, until a new version of Java adds more. Any shared Throwable will need to either break the contract of fillInStackTrace or behave very strangely. Further, a reused Throwable cannot reasonably change the message.

So you could kind of get away with it, but would you want to? Almost all of the performance issues (and you usually shouldn't be throwing exceptions too often) come down to fillInStackTrace. If you knock that out then there is little point is reuse.

(I prefer the phrase "static creation method" to "static factory method" because "factory" is way too overloaded.)

Tom Hawtin - tackline