We recently had a problem with a Java server application where the application was throwing Errors which were not caught because Error is a separate subclass of Throwable an
Do NOT ever catch Throwable
or Error
and you should generally not simply catch a generic Exception
either. Error
s are generally things that most reasonable programs cannot possibly recover from. If you know what is going on, you might be able to recover from one specific error, but in that case, you should catch only that one particular error and not all errors in general.
A good reason not to catch Error
is because of ThreadDeath. ThreadDeath
is a fairly normal occurrence that can theoretically be thrown from anywhere (other processes like the JVM itself can generate it), and the whole point of it is to kill your thread. ThreadDeath
is explicitly an Error
rather than an Exception
because too many people catch all Exception
s. If you ever were to catch ThreadDeath
, you must rethrow it so that your thread actually dies.
If you have control over the source, it should probably be restructured to throw an Exception
rather than an Error
. If you don't, you should probably call to the vendor and complain. Error
s should be reserved for only things that are terminal with no possible way to recover from them.
Usually Errors are problems you cannot possibly recover from, like OutOfMemoryError. There's nothing to do by catching them, so you should usually let them escape, and bring down the virtual machine.
Slightly off topic, but you may also want to look at this very good article about exceptions.
It all depends a bit on what you're going to do with an Error once you've caught it. In general, catching Errors probably shouldn't be seen as part of your "normal" exception flow. If you do catch one, you shouldn't be thinking about "carrying on as though nothing has happened", because the JVM (and various libraries) will use Errors as a way of signalling that "something really serious has happened and we need to shut down as soon as possible". In general, it's best to listen to them when they're telling you the end is nigh.
Another issue is that the recoverability or not from an Error may depend on the particular virtual machine, which is something you may or not have control over.
That said, there are a few corner cases where it is safe and/or desirable to catch Errors, or at least certain subclasses:
So the bottom line is: if you do catch Throwable/Error rather than Exception, it should be a well-defined case where you know you're "doing something special".
Edit: Possibly this is obvious, but I forgot to say that in practice, the JVM might not actually invoke your catch clause on an Error. I've definitely seen Hotspot glibly gloss over attempts to catch certain OutOfMemoryErrors and NoClassDefFoundError.
I know it might be counter-intuitive, but just because you can catch all sorts of Exceptions and Throwables and Errors does not mean you should.
Over-aggressive catching of java.lang.Exception can lead to some serious bugs in applications - because unexpected Exceptions never bubble up, are never caught during development/testing, etc.
Best practice: only catch
Normally when programming, you should only catch a specific exception (such as IOException
). In a lot of programs you can see a very toplevel
try {
...
} catch(Exception e) {
...
}
That catches all errors which could be recoverable and all those which indicate a bug in your code, e.g. InvalidArgumentException
, NullPointerException
. You can then automatically send an eMail, display a message box or whatever you like, since the JavaVM itself is still working fine.
Everything derived from Error
is something very bad, you can't do anything against. The question is, if it makes sense to catch a OutOfMemoryError
or a VirtualMachineError
. (It is a error in the JavaVM itself, probably you can't even display a message box or send an eMail then)
You should probably not a class derived from Error
, you should derive from Exception
or RuntimeException
.