Interesting question came up with a friend recently. When coding an application server in Java, how far should we be willing to go regarding catching and handling errors.
Exceptions are generally well-categorized and the recovery process is straight-forwards. Errors, however, seem to be less easy to diagnose and it's not always clear whether something has gone "wrong enough" that stopping service is advisable.
In practice, it seems the formal Sun recommendation would be to never catch errors. Admittedly, I've seen few errors that don't result from OS, hardware issues, or bad class linkage. Still, the notion that someone's poorly coded servlet could throw an error and result in loss of service for everyone seems too far to the other extreme. We came to some of our own guidelines, but I was very interested in opening the topic up to the kind of truly expert advice I see on these forums.
Sun's recommendations make sense. The only reason why error catching can be used is to notify service support about problems with the system (such as by sending an SMS or a e-mail).
However, error handling is almost never useful. Most of the time it is not possible to handle errors programmatically. In the vast majority of cases a thrown error means that the service needs to be stopped and errors must be fixed (by fixing code, replacing hardware, repackaging application). OutOfMemoryError, LinkageError - what can you do programmatically about it?
The Errors fall into at least 3 categories:
1. Hardware/Runtime Environment errors.
Errors like IOError, AWTError cannot be handled. This means that something is wrong with either the hardware and it needs to be fixed or repaired or with the JVM itself, and it probably needs to be reinstalled (or updated).
This cannot be handled programmatically.
This means that target environment has not been set up correctly. LinkageError and its descendants, such as NoClassDefFoundError, mean that an application is simply missing certain libraries and/or their versions are not compatible.
This is a deployment error, that means that an application needs to be repackaged and redeployed. This cannot be handled programmatically.
3. Runtime problems.
While they looks similar to RuntimeException, they are different in essense. Errors like StackOverflowError, OutOfMemoryError mean either a programmer's error or lack of resources. The only way to fix these errors is either fix the code or add more hardware resources (typically memory).
They cannot be handled programmatically.
4. Assertion errors.
Assertion errors that code does not behave as expected. This means that the code does not behave as expected. This can be either fixed by modifying the code or by disabling assertions. Both ways require system restart.
Again, these errors cannot be handled programmatically.
To sum up, there are no reasons to disagree with Sun's recommendations. You cannot handle Errors and you don't need to. If there's something that needs to be thrown/caught/handled, than it is an Exception, not an Error.
I greatly appreciate the detail in this response Sergei! Thanks for taking the time to advise on this matter.
Does it change the answer if we assume some tasks are non-essential? In other words, if we assume the app server can continue to run stably and provide value even if a single servlet request cannot be programmatically handled?
Let's say a poorly written servlet attempts to read posted data into a String, and let's say for the sake of argument this String is enough to run our application server out of memory. It seems we could conceivably recover programmatically from an OutOfMemoryError where the allocated resources are not essential to servicing other application server requests, but I recognize this may or may not work in practice.
Another extreme example of an error we cannot prevent/repair programmatically might be a servlet author actually throwing an error and taking down the application server for little or no reason. It seems we could continue to take requests, though we cannot prevent that code from executing as written.
What I described in my post relates to general scenarios. Of course in practice there can be exceptions (make sure they are not errors! :) ).
But I can't see how your situation is exceptional here in terms of handling errors.
"...Let's say a poorly written servlet..." - sounds to me like something that needs to be rewritten.
There is still nothing here about handling errors. What you suggest is keep running a server instance once an error has been caught. You can do that, if there is no other way to handle the situation (although you might get nasty surprises).
"Another extreme example of an error we cannot prevent/repair programmatically might be a servlet author actually throwing an error and taking down the application server for little or no reason. It seems we could continue to take requests, though we cannot prevent that code from executing as written." - how do you expect to handle requests if a server is down?
The problem is that by catching these errors you will not be able to fix the situation.
Java Development on Demand