I have a class the implements A
which will run a certain method of class B
. There is a requirement that this A
should never crash when running this operation (which is not possible, right?).
To reduce the chance of crashing I'm catching Throwable
around the operation, like so:
public void method(B b)
{
try
{
b.operation
}
catch(Throwable e)
{
//Log e
//Clean up stuff
}
}
My questions are:
- Would this actually help in reducing crashes caused by any thrown
Error
? - Is it a good idea to ever catch an
Error
?
4 Answers 4
Simple Answers: No and no.
For example catching an OutOfMemoryError
can be bad as without memory what could you do?
Also all other errors are most likely indicate some more serious error where you can do nothing.
For reference see the errors in the package java.lang and decide for every one what you will do when you catch it. If you're happy you will find that perhaps every tenth error could be handled by you.
-
But are there any other Errors that can be "handled"?Adam– Adam2014年10月06日 14:22:01 +00:00Commented Oct 6, 2014 at 14:22
-
3@Adam No, there are none. One of the reasons they are not exceptions is stated right on the
Error
class - reasonable applications should not catch these. Another trait is thatError
s are not local. For most exceptions all side effects are in the calling method, for anError
that is not the case.Ordous– Ordous2014年10月06日 14:24:45 +00:00Commented Oct 6, 2014 at 14:24 -
1Usually you'd catch an OOME at a pretty high level, with many objects going out of scope and freeing up space. And if the error was caused by a single oversized allocation request, then there really is no problem at all.Michael Borgwardt– Michael Borgwardt2014年10月06日 15:05:21 +00:00Commented Oct 6, 2014 at 15:05
-
3@MichaelBorgwardt actually is quite the opposite, catching an OOME might make some sense at low level (say, I am requesting a 30 MB+ buffer to load a video file). In that case, you can expect and deal with the error easily (just replacing it with an exception/could not load control code). If you just capture the error at high level, the state of the system would be unknown (it is unknown which operations failed), and the only realistic option would be "resetting" all of the program states.SJuan76– SJuan762014年10月06日 16:26:42 +00:00Commented Oct 6, 2014 at 16:26
-
1So I agree that catching
Error
s is often futile, but contrary to some of the absolute statements here, there are legitimate circumstances to catchError
s.Brandon– Brandon2014年10月07日 19:11:00 +00:00Commented Oct 7, 2014 at 19:11
When you encounter an Error
, it typically means your program is now in an undefined state: a .class
file is corrupted, or memory is completely full, or you've run into an internal bug in the JVM, or something of similar severity. Ask yourself: even if you catch the Error
to prevent an immediate crash, is it meaningful to continue running under these circumstances? Can you trust the program to behave correctly afterward? What can you do to actually handle an Error
once you catch it?
If your "never crash" requirement means "never stop executing", then by all means, log and continue. Clearly your client believes that a misbehaving program is better than a terminated one. But if "never crash" means "never stop functioning", you should focus your defensive efforts elsewhere to prevent the Error
from occurring in the first place, let it terminate the program if it somehow occurs anyway, and configure your server to automatically restart the program if that happens.
In general, you should NEVER catch things like Exception, Throwable, or Error, but only those specific subclasses of those that your application can reasonably be expected to handle and survive (or at least log something useful about before crashing).
Exception handling is supposed to be just that, handling error conditions and dealing with them in such a way that the application can continue running or report what happened before terminating.
It's not meant to be error masking, hiding problems and then just try to continue as if nothing happened. Not only will it rarely work (it will rear its ugly head somewhere else in the application soon, making the problem worse as now you have even more corruption in your state and/or data, but you now have a problem that's that much harder to track down and debug, and eventually fix.
I won't write a java program without catching Throwable at the top level of every process. The caught error is (by definition) unexpected, and is a bug that needs to be logged and fixed. The errors you catch this way will surprise you, and you will never learn of them unless you make every possible attempt to get the word back from the real world to your development desk.
ExecutorService
will not stop running if your code throws an exception, it's just theRunnable
will stop and not be rescheduled. Other than that - Do you really need this particular module to continue working even if the rest of the app just went haywire?